views:

103

answers:

1

Hello. I am using setjmp and longjmp for the first time, and I ran across an issue that comes about when I wrap setjmp and longjmp. I boiled the code down to the following example:

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

jmp_buf jb;

int mywrap_save()
{
  int i = setjmp(jb);
  return i;
}

int mywrap_call()
{
  longjmp(jb, 1);
  printf("this shouldn't appear\n");
}

void example_wrap()
{
  if (mywrap_save() == 0){
    printf("wrap: try block\n");
    mywrap_call();
  } else {
    printf("wrap: catch block\n");
  }
}

void example_non_wrap()
{
  if (setjmp(jb) == 0){
    printf("non_wrap: try block\n");
    longjmp(jb, 1);
  }  else {
    printf("non_wrap: catch block\n");
  }
}

int main()
{
  example_wrap();
  example_non_wrap();
}

Initially I thought example_wrap() and example_non_wrap() would behave the same. However, the result of running the program (GCC 4.4, Linux):

wrap: try block
non_wrap: try block
non_wrap: catch block

If I trace the program in gdb, I see that even though mywrap_save() returns 1, the else branch after returning is oddly ignored. Can anyone explain what is going on?

+5  A: 
 The longjmp() routines may not be called after the routine which called
 the setjmp() routines returns.

In other words, you are screwing up your stack.

You might take a look at the assembly to see if you can piece together what's really happening.

WhirlWind
So you'll need to use a macro for `mywrap_save()`.
caf
Brilliant, that's exactly correct. I am dumb for not realizing it earlier. The code didn't crash, and hence I didn't catch it. Serves me right for using setjmp and longjmp :)
Max