7.3. Process TerminationSection 11.5) Exit FunctionsThree functions terminate a program normally: _exit and _Exit, which return to the kernel immediately, and exit, which performs certain cleanup processing and then returns to the kernel.
is the same asreturn(0); from the main function. ExampleThe program in Figure 7.1 is the classic "hello, world" example.When we compile and run the program in Figure 7.1, we see that the exit code is random. If we compile the same program on different systems, we are likely to get different exit codes, depending on the contents of the stack and register contents at the time that the main function returns:$ cc hello.c $ ./a.out hello, world $ echo $? print the exit status 13 Now if we enable the 1999 ISO C compiler extensions, we see that the exit code changes:$ cc -std=c99 hello.c enable gcc's 1999 ISO C extensions hello.c:4: warning: return type defaults to 'int' $ ./a.out hello, world $ echo $? role="italicAlt"print the exit status 0 Note the compiler warning when we enable the 1999 ISO C extensions. This warning is printed because the type of the main function is not explicitly declared to be an integer. If we were to add this declaration, the message would go away. However, if we were to enable all recommended warnings from the compiler (with the -Wall flag), then we would see a warning message something like "control reaches end of nonvoid function."The declaration of main as returning an integer and the use of exit instead of return produces needless warnings from some compilers and the lint(1) program. The problem is that these compilers don't know that an exit from main is the same as a return. One way around these warnings, which become annoying after a while, is to use return instead of exit from main. But doing this prevents us from using the UNIX System's grep utility to locate all calls to exit from a program. Another solution is to declare main as returning void, instead of int, and continue calling exit. This gets rid of the compiler warning but doesn't look right (especially in a programming text), and can generate other compiler warnings, since the return type of main is supposed to be a signed integer. In this text, we show main as returning an integer, since that is the definition specified by both ISO C and POSIX.1.Different compilers vary in the verbosity of their warnings. Note that the GNU C compiler usually doesn't emit these extraneous compiler warnings unless additional warning options are used. Figure 7.1. Classic C program#include <stdio.h> main() { printf("hello, world\n"); } In the next chapter, we'll see how any process can cause a program to be executed, wait for the process to complete, and then fetch its exit status. atexit FunctionWith ISO C, a process can register up to 32 functions that are automatically called by exit. These are called exit handlers and are registered by calling the atexit function.
Figure 7.2. How a C program is started and how it terminates[View full size image] ![]() ExampleThe program in Figure 7.3 demonstrates the use of the atexit function.Executing the program in Figure 7.3 yields$ ./a.out main is done first exit handler first exit handler second exit handler An exit handler is called once for each time it is registered. In Figure 7.3, the first exit handler is registered twice, so it is called two times. Note that we don't call exit; instead, we return from main. Figure 7.3. Example of exit handlers#include "apue.h" static void my_exit1(void); static void my_exit2(void); int main(void) { if (atexit(my_exit2) != 0) err_sys("can't register my_exit2"); if (atexit(my_exit1) != 0) err_sys("can't register my_exit1"); if (atexit(my_exit1) != 0) err_sys("can't register my_exit1"); printf("main is done\n"); return(0); } static void my_exit1(void) { printf("first exit handler\n"); } static void my_exit2(void) { printf("second exit handler\n"); } |