1

我不明白为什么在函数中,在语句 内部调用middleFunc()时会引发分段错误。entry_point(arg)if ( setjmp(middle) )

    #include <stdio.h>
    #include <setjmp.h>


    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);
    }

 }
4

1 回答 1

5

在您的代码中,行为未定义。middle完成执行后middleFunc(无论是通过正常完成还是通过另一个longjmp),您都不允许长跳转。

7.13.2.1 longjmp 函数

2该函数使用相应的参数在程序的同一调用中longjmp恢复最近一次调用宏所保存的环境。如果没有这样的调用,[...] 或者如果包含宏调用的函数在中间 [...] 中终止了执行248),则行为未定义。setjmpjmp_bufsetjmp

248)例如,通过执行return语句或因为另一个longjmp调用导致转移到setjmp嵌套调用集中较早的函数中的调用。

在您的代码middleFunc设置中,然后通过执行middle立即退出。之后跳转不再有效。您不再被允许从任何地方跳转。机制只支持向上跳转调用栈。你不能做侧跳或下跳。仅支持向上跳转。mainlongjmp(start,1)middlemiddlesetjmp/longjmp

从实际的角度来看,您正试图跳入“死”函数调用,并且以某种方式期望函数参数值仍然有效(例如,从先前的调用中保留或其他内容)。但他们不是。setjmp/longjmp不要保留/恢复参数值。entry_point那个“死”调用中的值可能是一些垃圾。当您尝试通过 拨打电话时entry_point,代码核心转储。

setjmp/longjmpPS确实有时会使用侧跳来实现协程。但是,这种用法超出了标准库规范的范围。并且在任何情况下,这种用法都不会期望保留参数值。

于 2018-07-26T18:52:40.410 回答