c / expert
Snippet
Nicht-lokaler Ausführungs-Steuerfluss und Ausnahme-Emulation via setjmp und longjmp
Der C-Standard-Header <setjmp.h> bietet nicht-lokale Sprünge unter Umgehung normaler Stack-Unwind-Mechanismen. Ein Aufruf von setjmp speichert Registerzustände in einem jmp_buf-Puffer. Variablen, die zwischen setjmp und longjmp verändert werden, müssen als volatile deklariert werden, um Speicherungs- / Optimierungskonflikte bei der Wiederherstellung der Register zu vermeiden.
snippet.c
c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <stdio.h>#include <setjmp.h>static jmp_buf execution_context;void deep_calculation(volatile int *status_code) {if (*status_code < 0) {/* Perform non-local goto restoring stack context saved by setjmp */longjmp(execution_context, 404);}}int main(void) {/* Variables modified between setjmp and longjmp must be volatile to prevent clobbering */volatile int state = -1;int result = setjmp(execution_context);if (result == 0) {printf("Context saved. Executing operation...\n");deep_calculation(&state);} else {printf("Caught exception with code: %d\n", result);}return 0;}
Erklärung
1
volatile int state = -1;
Deklariert die Variable als volatile, damit ihr Wert bei der Register-Wiederherstellung durch longjmp erhalten bleibt.
2
int result = setjmp(execution_context);
Speichert den Registerzustand der Ausführungsumgebung; liefert 0 beim Erstellen und Nicht-Null bei Rückkehr via longjmp.