main主函數執行完畢後,是否可能會再執行一段代碼?
先看代碼,代碼為王!
#include <stdlib.h>
#include <stdio.h>
int fn1(void), fn2(void), fn3(void), fn4 (void);
void main( void )
{
_onexit( fn1 );
_onexit( fn2 );
_onexit( fn3 );
_onexit( fn4 );
printf( "This is executed first./n" );
}
int fn1()
{
printf( "next./n" );
return 0;
}
int fn2()
{
printf( "executed " );
return 0;
}
int fn3()
{
printf( "is " );
return 0;
}
int fn4()
{
printf( "This " );
return 0;
}
Output :
This is executed first.
This is executed next.
**********************************************************************************
crt會執行另一些代碼,進行處理工作。
如果你需要加入一段在main退出後執行的代碼,可以使用atexit()函數,註冊一個函數。
文法:
#include <stdlib.h>
int atexit(void (*function")(void));
#include <stdlib.h>
#include <stdio.h>
void fn1( void ), fn2( void ), fn3( void ), fn4( void );
int main( void )
{
atexit( fn1 );
atexit( fn2 );
atexit( fn3 );
atexit( fn4 );
printf( "This is executed first./n" );
}
void fn1()
{
printf( "next./n" );
}
void fn2()
{
printf( "executed " );
}
void fn3()
{
printf( "is " );
}
void fn4()
{
printf( "This " );
}
*********************************************************************************
其實main是在
mainCRTStartup中被調用的
在main之前會調用一系列初始化函數來初始化這個進程
而在main之後會調用exit(int)來進行進程的清理工作
#ifdef WPRFLAG
__winitenv = _wenviron;
mainret = wmain(__argc, __wargv, _wenviron);
#else /* WPRFLAG */
__initenv = _environ;
mainret = main(__argc, __argv, _environ);
#endif /* WPRFLAG */
#endif /* _WINMAIN_ */
exit(mainret);
樓上是說onexit是在main()之前, 來看看代碼便知
exit的代碼
void __cdecl exit ( int code )
{
doexit(code, 0, 0); /* full term, kill process */
}
doexit的代碼
static void __cdecl doexit (int code, int quick, int retcaller)
{
#ifdef _DEBUG
static int fExit = 0;
#endif /* _DEBUG */
#ifdef _MT
_lockexit(); /* assure only 1 thread in exit path */
#endif /*_MT */
if (_C_Exit_Done == TRUE) /* if doexit() is being called recursively */
TerminateProcess(GetCurrentProcess(),code); /* terminate with extreme prejudice */
_C_Termination_Done = TRUE;
/* save callable exit flag (for use by terminators) */
_exitflag = (char) retcaller; /* 0 = term, !0 = callable exit */
if (!quick) {
/*
* do _onexit/atexit() terminators
* (if there are any)
*
* These terminators MUST be executed in reverse order (LIFO)!
*
* NOTE:
* This code assumes that __onexitbegin points
* to the first valid onexit() entry and that
* __onexitend points past the last valid entry.
* If __onexitbegin == __onexitend, the table
* is empty and there are no routines to call.
*/
if (__onexitbegin) {
_PVFV * pfend = __onexitend;
while ( --pfend >= __onexitbegin )
/*
* if current table entry is non-NULL,
* call thru it.
*/
if ( *pfend != NULL )
(**pfend)(); // 在這裡迴圈調用onexit
}
/*
* do pre-terminators
*/
_initterm(__xp_a, __xp_z);
}
/ *
* do terminators
*/
_initterm(__xt_a, __xt_z);
#ifndef CRTDLL
#ifdef _DEBUG
/* Dump all memory leaks */
if (!fExit && _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) & _CRTDBG_LEAK_CHECK_DF)
{
fExit = 1;
_CrtDumpMemoryLeaks();
}
#endif /* _DEBUG */
#endif /* CRTDLL */
/* return to OS or to caller */
if (retcaller) {
#ifdef _MT
_unlockexit(); /* unlock the exit code path */
#endif /* _MT */
return;
}
_C_Exit_Done = TRUE;
ExitProcess(code);
}