Pourquoi une erreur de segmentation survient lors de l’appel d’une fonction dans setjmp ()?

Je ne comprends pas pourquoi dans la fonction middleFunc() , une erreur de segmentation est générée lorsque entry_point(arg) est if ( setjmp(middle) ) dans l’ if ( setjmp(middle) ) .

  #include  #include  jmp_buf start,middle,end; void finalFunc(void *v) { printf("hello\n"); return ; } void middleFunc(void (*entry_point)(void *), void *arg) { //just debug : this does not cause segmentation fault entry_point(arg); if ( setjmp(middle) ){ //this casues the segmentation fault entry_point(arg); //once the entry point (finalFunc) is executed go to jmp_buffer end longjmp(end,1); } else { longjmp(start,1); } } int main(){ if (setjmp(end)){ //exit since finalFunc has been executed return 0; } if (setjmp(start)){ //the middleFunc has previously set the jmp_buffer middle longjmp(middle,1); } else{ int x = 1; middleFunc(finalFunc,(void*)&x); } } 

Dans votre code, le comportement n’est pas défini. Vous n’êtes pas autorisé à faire un saut en longueur au middle après l’exécution de middleFunc (soit par achèvement normal, soit par un autre longjmp ).

7.13.2.1 La fonction longjmp

2 La fonction longjmp restaure l’environnement enregistré par la dernière invocation de la macro setjmp dans la même invocation du programme avec l’argument jmp_buf correspondant. S’il n’y a pas eu d’appel de ce type, ou si la […] fonction contenant l’appel de la macro setjmp a mis fin à l’exécution 248), le comportement n’est pas défini.

248) Par exemple, en exécutant une instruction return ou parce qu’un autre appel longjmp a provoqué un transfert vers une invocation setjmp dans une fonction antérieure de l’ensemble des appels nesteds.

Dans votre code, middleFunc définit middle et après cela, quitte immédiatement main en faisant longjmp(start,1) . Après ce saut middle n’est plus valide. Vous n’êtes plus autorisé à sauter au middle de n’importe où. setjmp/longjmp mécanisme setjmp/longjmp ne prend en charge que les sauts de la stack d’appels. Vous ne pouvez pas faire de sauts de côté ou de bas. Seuls les sauts sont pris en charge.

D’un sharepoint vue pratique, vous essayez de sauter dans une invocation de fonction “morte” et vous attendez en quelque sorte que ses valeurs de paramètre de fonction soient toujours valides (comme préservées de l’invocation précédente ou de quelque chose). Mais ils ne sont pas. setjmp/longjmp ne conserve / rétablit pas les valeurs des parameters. La valeur de entry_point dans cette invocation “dead” est probablement une foutaise . Lorsque vous essayez de passer un appel via entry_point , le code est envoyé.

PS Il est vrai que les sauts de côté avec setjmp/longjmp sont parfois utilisés pour mettre en œuvre des co-routines. Cependant, une telle utilisation dépasse les limites de la spécification de bibliothèque standard. Et dans tous les cas, une telle utilisation ne s’attendra jamais à la préservation des valeurs des parameters.