为什么调用 setjmp() 中的函数会发生分段错误? [英] Why a segmentation fault occurs calling a function inside setjmp()?

查看:44
本文介绍了为什么调用 setjmp() 中的函数会发生分段错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不明白为什么在函数 middleFunc() 中,当 entry_point(arg)if ( setjmp(中) ) 语句.

I do not understand why in the function middleFunc(), a segmentation fault is raisen when entry_point(arg) is invoked inside the if ( setjmp(middle) ) statement.

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

 }

推荐答案

在您的代码中,行为未定义.middleFunc 完成执行后(通过正常完成或另一个longjmp),您不能长跳转到middle.

In your code the behavior is undefined. You are not allowed to long-jump to middle after middleFunc finished execution (either by normal completion or by another longjmp).

7.13.2.1 longjmp 函数

2 longjmp 函数恢复最近一次调用 setjmp 宏时保存的环境对应的 jmp_buf 参数.如果没有这样的调用,[...] 或者如果包含 setjmp 宏调用的函数在中间 [...] 行为未定义.

2 The longjmp function restores the environment saved by the most recent invocation of the setjmp macro in the same invocation of the program with the corresponding jmp_buf argument. If there has been no such invocation, [...] or if the function containing the invocation of the setjmp macro has terminated execution248) in the interim [...] the behavior is undefined.

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

248) For example, by executing a return statement or because another longjmp call has caused a transfer to a setjmp invocation in a function earlier in the set of nested calls.

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

In your code middleFunc sets up middle and after that immediately exits to main by doing longjmp(start,1). After that jump middle is no longer valid. You are no longer allowed to jump to middle from anywhere. setjmp/longjmp mechanism only supports jumps up the call stack. You cannot do side-jumps or down-jumps. Only up-jumps are supported.

从实际的角度来看,您正试图跳入一个死"的函数调用,并以某种方式期望函数参数值仍然有效(例如,从先前的调用中保留下来或其他东西).但他们不是.setjmp/longjmp 不保存/恢复参数值.entry_point 在那个死"调用中的价值可能是一些垃圾.当您尝试通过 entry_point 进行调用时,代码核心转储.

From the practical point of view, you are attempting to jump into a "dead" function invocation and somehow expecting that function parameter values are still valid (like, preserved from the previous invocation or something). But they are not. setjmp/longjmp do not preserve/restore parameter values. Value of entry_point in that "dead" invocation is probably some garbage. When you attempt to make a call through entry_point, the code coredumps.

附言确实,有时会使用 setjmp/longjmp 进行侧跳来实现协同例程.但是,这种用法超出了标准库规范的范围.在任何情况下,这种用法都不会期望保留参数值.

P.S. It is true that side-jumping with setjmp/longjmp is sometimes used to implement co-routines. However, such usage falls outside the boundaries of standard library specification. And in any case such usage will never expect preservation of parameter values.

这篇关于为什么调用 setjmp() 中的函数会发生分段错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆