c / expert
Snippet
Nicht-lokales Stack-Unwinding mit setjmp und longjmp
In reinen C ermöglichen nicht-lokale Sprünge über setjmp und longjmp die Umgehung von dazwischenliegenden Stack-Frames im Kontrollfluss. Der Aufruf von setjmp speichert die Ausführungsumgebung (Stack-Pointer, Befehlszeiger und Register) in einem jmp_buf-Objekt. Wird anschließend longjmp aufgerufen, wird der Stack direkt zum Aufrufort von setjmp zurückgesetzt, als hätte setjmp den an longjmp übergebenen Wert zurückgegeben. Dieser Mechanismus bildet die Grundlage für benutzerdefinierte C-Ausnahmebehandlungen.
snippet.c
c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>#include <setjmp.h>static jmp_buf exception_env;void do_risky_operation(int count) {if (count < 0) {longjmp(exception_env, 1);}printf("Operation succeeded with count %d\n", count);}int main(void) {if (setjmp(exception_env) == 0) {do_risky_operation(-5);} else {printf("Caught exception: invalid negative count\n");}return 0;}
Erklärung
1
static jmp_buf exception_env;
Deklariert den Puffer für den Ausführungskontext zur Wiederherstellung bei nicht-lokalen Sprüngen.
2
if (setjmp(exception_env) == 0)
Speichert den Zustand und gibt initial 0 zurück; wertet nach Rückkehr via longjmp zu ungleich 0 aus.
3
longjmp(exception_env, 1);
Stellt die im Puffer gespeicherte Umgebung wieder her und übergibt die Kontrolle an setjmp.