對c語言有所了解的人都知道main函式是整個程式的入口,但是其實不然,在核心中可以使用鏈結器來設定程式的開始地方。
當核心使⽤⼀個exec函式執⾏c程式時,在調⽤main函式之前先調⽤⼀個特殊的啟動例程,可執⾏程式將此例程指定為程式的起始位址。啟動例程從核心獲取命令⾏引數和環境變數,然後為調⽤main函式做好準備。
前面我們關注的是程式開始進入時的呼叫函式,而atexit函式是乙個特殊的函式,它是在正常程式退出時呼叫的函式,我們把他叫為登記函式(函式原型:
int atexit (void (*)(void))
):
⼀個程序可以登記若⼲個(具體⾃⼰驗證⼀下)個函式,這些函式由exit⾃動調⽤,這些函式被稱為終⽌處理函式, atexit函式可以登記這些函式。 exit調⽤終⽌處理函式的順序和atexit登記的順序相反(網上很多說造成順序相反的原因是引數壓棧造成的,引數的壓棧是先進後出,和函式的棧幀相同),如果⼀個函式被多次登記,也會被多次調⽤。
以下函式的呼叫時程式異常或者正常終止:
程序終⽌的⽅式有8種,前5種為正常終⽌,後三種為異常終⽌:
1 從main函式返回;
2 調⽤exit函式;
3 調⽤_exit或_exit;
4 最後⼀個執行緒從啟動例程返回;
5 最後⼀個執行緒調⽤pthread_exit;
6 調⽤abort函式;
7 接到⼀個訊號並終⽌;
8 最後⼀個執行緒對取消請求做出響應。
exit()和_exit()以及_exit()函式的本質區別是是否立即進入核心,_exit()以及_exit()函式都是在呼叫後立即進入核心,而不會執行一些清理處理,但是exit()則會執行一些清理處理,這也是為什麼會存在atexit()函式的原因,因為exit()函式需要執行清理處理,需要執行一系列的操作,這些終止處理函式實際上就是完成各種所謂的清除操作的實際執行體。
下面我們來驗證atexit的呼叫順序和退出順序:
#include#includevoid func1()
void func2()
void func3()
int main()
執行截圖:
我們可以看到atexit函式的呼叫順序是和登記順序相反的。
atexit函式的用途也是比較廣泛的:
可以按照你予設的順序摧毀全域性變數(類),例如有個log類,你在其它的全域性類裡也有可能呼叫到log類寫日誌。所以log 類必須最後被析構 。假如沒有規定析構順序,那麼程式在退出時將有可能首先析構log類,那麼其它的全域性類在此時將無法正確寫日誌。 把資料寫回檔案, 刪除臨時檔案, 這才是真正有用的.
atexit函式詳解
對c語言有所了解的人都知道main函式是整個程式的入口,但是其實不然,在核心中可以使用鏈結器來設定程式的開始地方。當核心使 個exec函式執 c程式時,在調 main函式之前先調 個特殊的啟動例程,可執 程式將此例程指定為程式的起始位址。啟動例程從核心獲取命令 引數和環境變數,然後為調 main函式...
atexit函式詳解
對c語言有所了解的人都知道main函式是整個程式的入口,但是其實不然,在核心中可以使用鏈結器來設定程式的開始地方。當核心使 個exec函式執 c程式時,在調 main函式之前先調 個特殊的啟動例程,可執 程式將此例程指定為程式的起始位址。啟動例程從核心獲取命令 引數和環境變數,然後為調 main函式...
atexit 函式呼叫
函式名 atexit 標頭檔案 include 功 能 註冊終止函式 即main執行結束後呼叫的函式 用 法 int atexit void func void 按照iso c的規定,乙個程序可以登記多達32個函式,這些函式將由exit自動呼叫。atexit 註冊的函式型別應為不接受任何引數的voi...