...
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 | ||||
|---|---|---|---|---|
| ||||
#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 | ||||
|---|---|---|---|---|
| ||||
#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 | ||||
|---|---|---|---|---|
| ||||
#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 | ||||
|---|---|---|---|---|
| ||||
#include <stdlib.h>
void exit1(void) {
/* ... */
return;
}
int main(void) {
if (atexit(exit1) != 0) {
/* Handle error */
}
/* ... */
exit(0);
}
|
...