C语言 failure of setjmp/longjmp



一段代码在这里

jmp_buf mark;
int Sub_Func()  
{  
    int be_modify, jmpret;    
    be_modify = 0;    
    jmpret = setjmp( mark );  
    if( jmpret == 0 )  
    {  
        // sth else here 
    }  
    else  
    {  
        // error handle 
        switch (jmpret)  
        {  
            case 1:  
                printf( "Error 1n");  
                break;  
            case 2:  
                printf( "Error 2n");  
                break;  
            case 3:  
                printf( "Error 3n");  
                break;  
            default :  
                printf( "Unknown Error");  
                break;  
        }  
        printf("after switchn");        
    }     
    return jmpret;  
}  
void main( void )  
{  
    Sub_Func();   
    // the longjmp after setjmp
    longjmp(mark, 1);  
}  

结果是:
错误 1
切换
后分段错误

我知道原因可能是 longjmp 跳回到上一个堆栈。 但我不确定细节,以及"标记"中存储了什么样的值,谁能解释一下?

setjmp()并通过记录堆栈帧位置来longjmp()工作。如果在 Sub_Func() 中记录堆栈帧,但在调用 longjmp() 之前从函数返回,则堆栈帧不再有效。 longjmp() 意味着在与 setjmp() 相同的函数中调用(子函数是可以的)。

您正在尝试将 longjmp 返回到更深层次的函数。您只能长 jmp 回到较浅的函数。

因此,如果 A 调用 setjmp ,然后调用 B,则 B 可以longjmp回 A。

但如果A调用B,B调用setjmp,B返回A,A不能longjmp回B。

您通过违反以下 (7.13.2.1) 调用了未定义的行为:

longjmp 函数使用相应的 jmp_buf 参数恢复最近一次调用 setjmp 宏时保存的环境。如果没有这样的调用,或者包含 setjmp 宏调用的函数在此期间终止了 execution217),或者如果 setjmp 宏的调用在具有可变修改类型的标识符的范围内,并且执行在此期间离开了该范围,则行为是未定义的。

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

简而言之,longjmp不能用于跳转到已返回的函数中的setjmp点。

最新更新