longjmp() ist definiert in der setjmp
, die in C über setjmp.h
, bzw. in C++ über csetjmp
eingebunden wird.
longjmp() springt an ein Ziel, das über die übergebene Umgebungs-Struktur definiert ist.
Dabei wird noch ein Integer übergeben, der danach von setjmp
an der Ziel-Stelle zurückgegeben wird.
longjmp( env, 123 );
#include <setjmp.h> void longjmp( jmp_buf env, int val );
env: Die wiederherzustellende Umgebung
val: Rückgabewert von setjmp
am Ziel
Im folgenden Beispiel werden 4 Ziel-Punkte definiert. An welchen Punkt gesprungen wird, wird über argv
definiert. Dabei wird die Nummer des Sprungpunktes (1, 2 oder 3) eingegeben. Bei jeder anderen Eingabe oder wenn alle Punkte abgearbeitet wurden, wird an den letzte Punkt gesprungen.
#include <stdio.h> #include <stdlib.h> #include <setjmp.h> int main( int argc, char *argv[] ) { // 3 Umgebungen zwischen denen gesprungen werden kann und Ende des Programms jmp_buf env1, env2, env3, envEnd; // Index des nächsten Zieles in 'argv' int dstIndex = 0; // Nächstes Ziel int dst; // 1. Ziel-Punkt setzen dstIndex = setjmp( env1 ); // Prüfen, ob wir nicht beim allerersten Durchlauf sind if( dstIndex != 0 ) { printf( "Zu 1 gesprungen\n" ); // Bei ungültigem Index wird das Programm beendet if( dstIndex >= argc ) longjmp( envEnd, -1 ); // Ziel aus 'argv' auslesen dst = atoi( argv[dstIndex] ); // An das Ziel springen bzw. ans Ende, // wenn das Ziel nicht gültig ist switch( dst ) { case 1: longjmp( env1, dstIndex + 1 ); break; case 2: longjmp( env2, dstIndex + 1 ); break; case 3: longjmp( env3, dstIndex + 1 ); break; default: longjmp( envEnd, dstIndex + 1 ); } } // 2. Ziel-Punkt setzen dstIndex = setjmp( env2 ); if( dstIndex != 0 ) { printf( "Zu 2 gesprungen\n" ); // Bei ungültigem Index wird das Programm beendet if( dstIndex >= argc ) longjmp( envEnd, -1 ); // Ziel aus 'argv' auslesen dst = atoi( argv[dstIndex] ); // An das Ziel springen bzw. ans Ende, // wenn das Ziel nicht gültig ist switch( dst ) { case 1: longjmp( env1, dstIndex + 1 ); break; case 2: longjmp( env2, dstIndex + 1 ); break; case 3: longjmp( env3, dstIndex + 1 ); break; default: longjmp( envEnd, dstIndex + 1 ); } } // 3. Ziel-Punkt setzen dstIndex = setjmp( env3 ); if( dstIndex != 0 ) { printf( "Zu 3 gesprungen\n" ); // Bei ungültigem Index wird das Programm beendet if( dstIndex >= argc ) longjmp( envEnd, -1 ); // Ziel aus 'argv' auslesen dst = atoi( argv[dstIndex] ); // An das Ziel springen bzw. ans Ende, // wenn das Ziel nicht gültig ist switch( dst ) { case 1: longjmp( env1, dstIndex + 1 ); break; case 2: longjmp( env2, dstIndex + 1 ); break; case 3: longjmp( env3, dstIndex + 1 ); break; default: longjmp( envEnd, dstIndex + 1 ); } } // End-Ziel-Punkt setzen dstIndex = setjmp( envEnd ); if( dstIndex == 0 ) { // Hier beginnt der eigentliche Programmablauf. Alle // Ziele wurden gesetzt und sind dadurch erreichbar. // Der Ziel-Index wird um 1 erhöht, da das erste // Element von 'argv' mit dem Programm-Pfad gefüllt // ist. dstIndex++; printf( "Beginn des Programms\n" ); // Bei ungültigem Index wird das Programm beendet if( dstIndex >= argc ) longjmp( envEnd, -1 ); // Ziel aus 'argv' auslesen dst = atoi( argv[dstIndex] ); // An das Ziel springen bzw. ans Ende, // wenn das Ziel nicht gültig ist switch( dst ) { case 1: longjmp( env1, dstIndex + 1 ); break; case 2: longjmp( env2, dstIndex + 1 ); break; case 3: longjmp( env3, dstIndex + 1 ); break; default: longjmp( envEnd, dstIndex + 1 ); } } else { // Entweder durch eine ungültige Eingabe // oder durch das Abarbeiten des letzten // Zieles wurde das Ende erreicht. printf( "Programm beendet\n" ); } return 0; }
Ausgabe:
$ ./exception 1 2 3 Beginn des Programms Zu 1 gesprungen Zu 2 gesprungen Zu 3 gesprungen Programm beendet $ ./exception 1 2 3 2 1 4 Beginn des Programms Zu 1 gesprungen Zu 2 gesprungen Zu 3 gesprungen Zu 2 gesprungen Zu 1 gesprungen Programm beendet $ ./exception Beginn des Programms Programm beendet