Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

This noncompliant code example calls setjmp() in an assignment statement, resulting in undefined behavior.

Code Block
bgColor#FFCCCC
langc
jmp_buf buf;

void f(void) {
  int i = setjmp(buf);
  if (i == 0) {
    g();
  } else {
    /* longjmp was invoked */
  }
}

void g(void) {
  /* ... */
  longjmp(buf, 1);
}

...

Placing the call to setjmp() in the if statement and, optionally, comparing it with a constant integer removes the undefined behavior, as shown in this compliant solution.

Code Block
bgColor#ccccff
langc
jmp_buf buf;

void f(void) {
  if (setjmp(buf) == 0) {
    g();
  } else {
    /* longjmp was invoked */
  }
}

void g(void) {
  /* ... */
  longjmp(buf, 1);
}

...

Any attempt to invoke the longjmp() function to transfer control to a function that has completed execution results in undefined behavior.

Code Block
bgColor#FFCCCC
langc
jmp_buf buf;
unsigned char b[] = {0xe5, 0x06, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00};

int main(void) {
  setup();
  do_stuff();
  return 0;
}

void setup(void) {
  f();
}

void f(void) {
  g();
}

void g(void) {
  if (setjmp(buf) == 0) {
    printf("setjmp() invoked\n");
  } else {
    printf("longjmp() invoked\n");
  }
}

void do_stuff(void) {
  char a[8];
  memcpy(a, b, 8);
  /* ... stuff ... */
  longjmp(buf, 1);
}

void bad(void) {
  printf("Should not be called!\n");
  exit(1);
}

...

The longjmp() function should only be used when the function containing the corresponding setjmp() is guaranteed not to have completed execution, as in the following example:

Code Block
bgColor#ccccff
langc
jmp_buf buf;
unsigned char b[] = {0xe5, 0x06, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00};

int main(void) {
  if (setjmp(buf) == 0) {
    printf("setjmp() invoked\n");
  } else {
    printf("longjmp() invoked\n");
  }
  do_stuff();
  return 0;
}

void do_stuff(void) {
  char a[8];
  memcpy(a, b, 8);
  /* ... stuff ... */
  longjmp(buf, 1);
}

void bad(void) {
  printf("Should not be called!\n");
  exit(1);
}

...

In this noncompliant example, non-volatile-qualified objects local to the function that invoked the corresponding setjmp() have indeterminate values after longjmp() has been executed if their value has been changed since the invocation of setjmp().

Code Block
bgColor#FFCCCC
langc
jmp_buf buf;

void f(void) {
  int i = 0;
  if (setjmp(buf) != 0) {
    printf("%i\n", i);
    /* ... */
  }
  i = 2;
  g();
}

void g(void) {
  /* ... */
  longjmp(buf, 1);
}

...

If an object local to the function that invoked setjmp() needs to be accessed after longjmp() returns control to the function, the object should be volatile-qualified.

Code Block
bgColor#ccccff
langc
jmp_buf buf;

void f(void) {
  volatile int i = 0;
  if (setjmp(buf) != 0) {
    printf("%i\n", i);
    /* ... */
  }
  i = 2;
  g();
}

void g(void) {
  /* ... */
  longjmp(buf, 1);
}

...