Something after main function exits

When the program runs to the end of the main function, or more strictly, returns some value in main(), it means the whole program is over. However, we can do something which is not executed within the scope of main(). Of course, there should be some preparation work done before the main() exits. We type the following code to a cpp file, and then compile and run it:

#include <iostream>
using namespace std;

void f1(){ cout<<"f1()"<<endl; }
void f2(){ cout<<"f2()"<<endl; }
void f3(){ cout<<"f3()"<<endl; }

int main()
{
    atexit(f1);
    atexit(f2);
    atexit(f3);
    cout
<<"This is the end of main()."<<endl;
    
return 0;
}

The console will print:

This is the end of main().

f3()

f2()

f1()

The key method is atexit(). It can save some functions for execution at main's exit, and these functions can do something they like (Notice that the methods are executed in the opposite order of being registered). However, there are some strict limits to atexit(). The most important one is that the type of its parameter should be a pointer to a function which has no parameter and returns no value, i.e. the type of the parameter should be void (*)(void). Other types will cause an error in the compile time.

Then someone may be a little interested in atexit() and search for its declaration in the file "iostream". To his or her surprise, nothing relevant found. Actually, the code below can work very well:

void f1(){}
void f2(){}
void f3(){}

main()
{
    atexit(f1);
    atexit(f2);
    atexit(f3);
    
return 0;
}

Take Microsoft VC++ compiler for example. We can find out that the only declaration of atexit() is in stdlib.h. It is like this:

int __cdecl atexit(void (__cdecl *)(void));

(__cdecl is a flag for those non-Microsoft compilers. We can find the following code in many head files, such as fltintrn.h, heap.h, and so on.

#if(!defined(_MSC_VER) && !defined(__cdecl))
#define __cdecl
#endif

)

Therefore, a more strict usage is to include stdlib.h at the beginning of the program. Somebody may ask: why do we have to include that head file? The compiler will check it automatically even without stdlib.h. Well, C++ compilers will do it for you, but C compilers will not. You can change the return type of any of the three functions above and it will be ok with C compilers. So this is another proof that C++ compilers are more strict than C compilers.

All right. Then how to explain why atexit() can be used without any declaration and definition? I still can't tell it clearly. But I found there are something relevant to atexit() in these two files: _sampld_.def and _sample_.def, which are located in %visual studio home%/Vc7/crt/src/intel. There is some comment in both files:

/*This is the .DEF file for the Microsoft Visual C++ Run-time Library DLL
   The release version is _SAMPLE_.DLL and the debug version _SAMPLD_.DLL.
*/

I guess in compiling and linking period, the information of atexit() can be gotten from these four files. What do you think?

There is another way to save functions for execution at main's exit: _onexit(). However, its parameter type should be int (*)(void).

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章