對於進程或者線程而言,在結束時都有一個exit code。如果我們在windows的cmd中執行完一個程式後,那麼我們可以通過cmd的%ERRORLEVEL%變數來獲得程式的exit code。而在Linux的shell中,我們可以通過$?變數來獲得。
進程的exit code其實就是主線程的exit code,因為一個進程至少含有一個線程,而第一個被建立的線程稱之為主線程(main thread),其他線程稱之為輔助線程(worker thread)。
在win32上,對於C/C++程式而言,入口通常是main,而該函數的return code就是主線程,即進程的exit code了。同理,而對於線程而言,我們的線程函數的return code就是該線程的exit code了。
win32上一個進程的開始入口是由windows的BaseProcessStart開始的,最後才調用我們的main函數。
// real entry of a process<br />void BaseProcessStart(pStartAddr)<br />{<br /> __try {<br /> ExitThread(pStartAddr());<br /> } __except(UnhandledExceptionFilterGetExceptionInformation())) {<br /> ExitProcess(GetExceptionCode());<br /> }<br />}<br />
這裡我們可以看到調用了函數ExitThread,這裡是一個線程結束的地方,也就是主線程,如果我們的main函數沒有拋出什麼未處理的異常的話,那麼就會調用該函數。但是如果我們有未處理的異常,那麼最終會調用ExitProcess。而通常我們會在一個程式出現異常情況下,彈出一個系統對話方塊要求我們終止或者調試該程式,就是在處理未處理的異常時候發生的。這裡是在UnhandledExceptionFilterGetExeptionInfomation中彈出的對話方塊。
我們看到對於exit code可能有2種可能
- 要麼是main函數正常返回時的return code
- 要麼是Exception code(詳見MSDN中EXCEPTION_RECORD)
對於線程的exit code也是一樣。以下是線程真正的入口
void BaseThreadStart(pStartAddress, pParam)<br />{<br />__try {<br />ExitThread(pStartAddress(pParam));<br />} __except(UnhandledExceptionFilter(GetExceptionInformation())) {<br />ExitProcess(GetExceptionCode());<br />}<br />}<br />
對於以下程式,有一個除0錯誤,win32中對應的Exception code為EXCEPTION_INT_DIVIDE_BY_ZERO = 0xC000 0094
int main()<br />{<br /> int x = 0;<br /> int y = 0;<br /> x /= y; // divide by zero<br />}<br />
在cmd下執行該程式,獲得返回碼為-1073741676,這個值正好是EXCEPTION_INT_DIVIDE_BY_ZERO 的有符號表示。
但是在shell下執行該程式,獲得的返回碼為127。
根據linux中exit 的man page,exit的原型為
void exit(int status)
並且返回給父進程的最終的exit code的值是 status & 0377,也就是在0-255之間
但是傳回值127對於shell而言有特殊的意義——command not found。在這裡有部分特殊意義退出碼的列表。
進程的Exit Code最好有特殊的意義,這樣我們可以通過返回碼來瞭解一些關於進程意外結束的原因。