Comment fonctionnent les sauts non locaux en C définis dans setjmp.h?

L’Annexe B du Manuel de référence C décrit les deux fonctions setjmp et longjmp pour ce que l’on appelle des sauts non locaux . Mis à part la compréhension de base que setjmp enregistre les informations d’état et que longjmp restaure l’ state , je n’ai pas été en mesure de comprendre le déroulement exact et les cas d’utilisation de cette fonctionnalité.

Alors, qu’est-ce que cette fonctionnalité accomplit exactement et où est-elle utile?

En ce qui concerne le stream de contrôle: setjmp retourne deux fois et longjmp ne retourne jamais. Lorsque vous appelez setjmp pour la première fois pour stocker l’environnement, il renvoie zéro et lorsque vous appelez longjmp , le stream de contrôle passe à renvoyer de setjmp avec la valeur fournie dans l’argument.

(Notez que setjmp ne doit pas nécessairement être une fonction; il peut s’agir d’une macro. longjmp est une fonction.)

Les cas d’utilisation sont généralement cités comme “traitement des erreurs” et “n’utilisez pas ces fonctions”.

Voici un petit exemple de stream de contrôle:

 jmp_buf env; void foo() { longjmp(&env, 10); +---->----+ } | | | | int main() (entry)---+ ^ V { | | | if(setjmp(&env) == 0) | (= 0) | | (= 10) { | ^ | foo(); +---->----+ | } +---->----+ else | { | return 0; +--- (end) } } 

Remarques:

  • Vous ne pouvez pas passer 0 à longjmp . Si vous le faites, 1 est renvoyé par setjmp .

  • Vous ne devez pas retourner de la fonction qui a appelé setjmp avant le longjmp correspondant. En d’autres termes, longjmp doit uniquement être appelé au-dessus de setjmp dans la stack d’appels.

  • (Merci à @wildplasser 🙂 Vous ne pouvez pas stocker le résultat de setjmp . Si vous souhaitez revenir de différentes manières, vous pouvez utiliser un switch , cependant:

     switch (setjmp(&env)) { case 0: // first call case 2: // returned from longjmp(&env, 2) case 5: // returned from longjmp(&env, 5) // etc. }