Versions Compared

Key

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

...

In this noncompliant code example, the exit1() and exit2() functions are registered by atexit() to perform required cleanup upon program termination. However, if condition evaluates to true, exit() is called a second time, resulting in undefined behavior.

Code Block
bgColor#FFcccc
langc
#include <stdio.h>
#include <stdlib.h>

void exit1(void) {
  /* ...cleanup code... */
  return;
}

void exit2(void) {
  if (/* condition */) {
    /* ...more cleanup code... */
    exit(0);
  }
  return;
}

int main(void) {
  if (atexit(exit1) != 0) {
    /* Handle error */
  }
  if (atexit(exit2) != 0) {
    /* Handle error */
  }
  /* ...program code... */
  exit(0);
}

...

A function that is registered as an exit handler by atexit() must exit by returning, and not in any other manner.

Code Block
bgColor#ccccFF
langc
#include <stdio.h>
#include <stdlib.h>

void exit1(void) {
  /* ...cleanup code... */
  return;
}

void exit2(void) {
  if (/* condition */) {
    /* ...more cleanup code... */
  }
  return;
}

int main(void) {
  if (atexit(exit1) != 0) {
    /* Handle error */
  }
  if (atexit(exit2) != 0) {
    /* Handle error */
  }
  /* ...program code... */
  exit(0);
}

...

The function exit1() is registered by atexit(), so upon program termination, exit1() is called. Execution will jump back to main() and return, with undefined results.

Code Block
bgColor#FFcccc
langc
#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>

jmp_buf env;
int val;

void exit1(void) {
  /* ... */
  longjmp(env, 1);
}

int main(void) {
  if (atexit(exit1) != 0) {
    /* Handle error */
  }
  /* ... */
  if (setjmp(env) == 0) {
    exit(0);
  }
  else {
    return 0;
  }
}

...

Careful thought about program flow is the best prevention for an invalid call to longjmp(). After the exit function has been called, avoid using longjmp() where it will cause a function to terminate.

Code Block
bgColor#ccccFF
langc
#include <stdlib.h>

void exit1(void) {
  /* ... */
  return;
}

int main(void) {
  if (atexit(exit1) != 0) {
    /* Handle error */
  }
  /* ... */
  exit(0);
}

...