0

a piece of code here

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 1\n");  
                break;  
            case 2:  
                printf( "Error 2\n");  
                break;  
            case 3:  
                printf( "Error 3\n");  
                break;  
            default :  
                printf( "Unknown Error");  
                break;  
        }  
        printf("after switch\n");        
    }     
    return jmpret;  
}  

void main( void )  
{  
    Sub_Func();   
    // the longjmp after setjmp
    longjmp(mark, 1);  
}  

the result is:
Error 1
after switch
Segmentation fault

I know the reason maybe longjmp jump back to the previous stack. but I'm not sure about the detail, and what kind of value has been stored in 'mark', can anyone explain that?

nzomkxia
  • 1,219
  • 4
  • 16
  • 35
  • 2
    Please note: you cannot assign the "return" value from setjmp(); you can only evaluate it as an expression. Google: "setjmp assign" – wildplasser Jun 21 '12 at 14:00
  • @wildplasser sure you can, it's a normal function with a return value, no special language construct. – mensi Jun 21 '12 at 14:01
  • 1
    It is a *very special* function: it can return twice, once with return value=0, and once with return value != 0. – wildplasser Jun 21 '12 at 14:07
  • @mensi: you still have not googled it, have you? – wildplasser Jun 21 '12 at 21:41
  • @wildplasser what's your point? It is a normal function with a return value. That does say absolutely nothing about how many times a function returns. A function that never returns is trivial with `while(1)` and a function that returns X times is possible by using inline asm and either an auxiliary function like `longjmp` or alternatively something like the timer interrupt. There is nothing special about this. – mensi Jun 21 '12 at 22:53
  • 2
    mensi: you still have not googled it, have you? http://www.velocityreviews.com/forums/t648995-storing-setjmp-s-rv-in-a-variable.html https://www.securecoding.cert.org/confluence/display/seccode/ERR05-C.+Application-independent+code+should+provide+error+detection+without+dictating+error+handling http://www.archivum.info/comp.lang.c/2009-07/00732/setjmp-return-value-as-the-right-hand-side-of-a-assignment-expression.html And setjmp() is certaninly not an ordinary function. – wildplasser Jun 21 '12 at 23:07

3 Answers3

3

setjmp() and longjmp() work by recording a stack frame position. If you record the stack frame in Sub_Func() but return from the function before calling longjmp(), the stack frame is no more valid. longjmp() is meant to be called in the same function than setjmp() (subfunction is ok).

Yann Droneaud
  • 5,277
  • 1
  • 23
  • 39
  • 4
    And the appropriate section of the manpage: "The stack context will be invalidated if the function which called setjmp() returns." – mensi Jun 21 '12 at 14:00
  • @ydroneaud in the Sub_Func(), setjmp is called, so %ebp of Sub_Func() has been stored to the jmp_buf. In main(), longjmp is called. the result seems that it can be back to Sub_Func() and do sth, but fail after that. – nzomkxia Jun 22 '12 at 01:42
  • @nzomkxia you can't go back to a function you just leaved. The content of the stack frame registered by setjmp() is undefined (and certainly wrong). SEe others answers and comments. – Yann Droneaud Jun 22 '12 at 08:24
2

You are trying to longjmp back to a deeper function. You can only longjmp back to a shallower function.

So if A calls setjmp, then calls B, then B can longjmp back into A.

But if A calls b, B calls setjmp, B returns to A, A cannot longjmp back to B.

Ben
  • 34,935
  • 6
  • 74
  • 113
2

You have invoked undefined behavior by violating the following (7.13.2.1):

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 execution217) in the interim, or if the invocation of the setjmp macro was within the scope of an identifier with variably modified type and execution has left that scope in the interim, the behavior is undefined.

217) 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.

In short, longjmp cannot be used to jump to a setjmp point in a function which has already returned.

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711