C/C++ 中 exit() 函數的參數到底有什麼意義?

我知道0表示正常退出,非0表示錯誤退出,但是這參數究竟有什麼意義呢?據說面向對象中不建議使用exit()函數,如果是,這是為什麼呢,又該用什麼方法替換呢?


題主問的是這個返回值的意義,而非 exit() 的意義,很多人都沒說到點子。

C 語言的設計之初就是為 Unix 系統設計的,而這個系統是『很多程序互相配合』搭配成一個系統。

每個運行著的程序都是進程,而進程就會有父進程,父進程通常是直接啟動你的進程,父進程死亡的進程會被 init 收養,其父進程變為 init,而 init 的父進程是進程 0,進程 0 則是系統啟動時啟動的第一個進程。

exit() 裡面的參數,是傳遞給其父進程的。對父進程來說,你的進程彷彿是一個函數,而函數可以有返回值。

所以回答第一個問題:exit() 的參數,是給自己的父進程使用的。通常一個程序的父進程可能是任何進程,因此我們無法預期我們的父進程是否規定必須要有這個返回值,那麼我們應當提供這個返回值,以保證不同的父進程的需求得到滿足。

一個典型的例子是 make,Makefile 對於一個 target 下面有多條順序執行的語句,而 make 作為父進程,會檢查每個語句的返回值是否為 0 ,遇到任何一個非 0 值,都會停止當前 rule 的執行。而我們知道,make 實際上可以執行任何命令任何程序,因而任何被 make 調用的程序必須有正確的返回值。

另外一個問題,為什麼要使用 exit() 函數?

答:是歷史原因,雖然現在大多數平台下,直接在 main() 函數裡面 return 可以退出程序。但是在某些平台下,在 main() 函數裡面 return 會導致程序永遠不退出(因為代碼已經執行完畢,程序卻還沒有收到要退出的指令)。換句話說,為了兼容性考慮,在特定的平台下,程序最後一行必須使用 exit() 才能正常退出,這是 exit() 存在的重要價值。


這是Shell調用時所用的返回參數,0表示程序已經正常執行完畢,而非0值則表示有錯誤發生,至於非0值具體為多少則由開發者自己定義,比如1代表輸入錯誤,2代表計算錯誤之類的。

當然,也有一些是由系統定義的錯誤代碼,比如棧溢出、除零之類的錯誤。


在windows中,可以 CreateProcess, 得到一個 handle。

然後用 WaitForSingleObject 函數,等待這個進程退出,然後調用:

BOOL GetExitCodeProcess(HANDLE hProcess, LPDWORD lpExitCode);

得到你在 exit 或者 入口點函數中的返回值。

然後 CloseHandle ,關閉這個進程句柄。

好了,現在你知道,應該如何使用它了。你可以根據不同的 exit code ,得到該進程的對應的結果(當然,這是由你來定義的)。

如果你沒有這樣一個父進程來處理 exit code,當然,這個玩意你都沒有 get,自然寫幾都沒什麼關係啦!


「0表示正常退出」,這個說法問題不大。但「非0表示錯誤退出」這個說法值得商榷。實際上C標準只規定EXIT_FAILURE值表示程序執行失敗。其他的status值以及含義都是由實現自行規定的(implementation-defined)。

所以說,脫離實際的環境談這個問題是沒有確定答案的


exit相當於強行退出,之後任何代碼都得不到執行的機會。強行殺死進程而不是正常退出不是推薦的做法,不管是不是面向對象


1.Kernel必須提供一個使應用程序退出的方法/API。

Linux提供了exit,而NT提供了ExitProcess。

2.這個方法攜帶了進程退出時的信息,類比於函數的返回值。

標準定義了EXIT_SUCCESS和EXIT_FAILURE,實踐中常常用0和非0。

exit/ExitProcess可以由應用程序直接使用,暴力地結束掉自己。

也可以由編譯器或編譯器提供的運行庫使用,使用main的返回值作為參數。

還可能由操作系統本身使用。

它們也沒有返回值,因為它們確實不「返回」。

參考kernel/exit.c:

...

tsk-&>exit_code = code;

...

它基本銷毀了進程,只留下進程式控制制塊task。它裡面的信息還可以給

waitpid/GetExitCodeProcess之類的API使用。

------------------------------------------------------------------------------------------------------------

補充,關於從main或入口點返回:

應用程序的生與死都需要內核的支持。

Linux中通過fork產生新的進程和運行環境,而NT是通過APC機制跳進

新進程的ntdll.dll中特定地址初始化入口,建立新進程的運行環境。

運行在UserMode的應用程序沒辦法直接返回Kernel,也就不能退出自己。

內核需要提供提供一種退出的方式。

如果真的從入口返回,內核會捕獲進程異常(如果沒程序處理該異常),

並為它調用exit/ExitProcess。


在面向對象中,exit的話對象的析構函數不會被調用(但是定義為靜態的實例會被調用),原理還不知道。

exit的參數對於本進程來說是沒意義的,這個是給它的父進程用的,哪怕你進程正常結束你也可以返回非0值。


好吧,題主問題是兩個,我的理解是這樣問的:

問題1:exit()函數退出時,傳遞的傳數是起什麼作用的(給誰看的)?

問題2:面向對象編程時,還能不能使用exit()函數了,為什麼?如果不能,有什麼替代方案?

以下是回答:

對於第1個問題的回答:

這個函數(exitI())是由你自己的程序調用的,而參數是給執行你這行程序的調用者看的,例如:你的程序叫A,在A裡面寫一行exit();這是讓「系統」去執行這行代碼,因為你自己沒有寫過這個函數,所以是「系統」來執行的,所以「系統」會執行這行代碼,而參數是作用就是告訴系統,你是什麼狀態退出的,0表示正常退出,其它值為非正常退出,所以,系統有可能依據你的參數,做一些後續的工作:記下來這個程序是正常退出,還是異常退出,等等的工作;

第2個問題的回答:

就算是面向女朋友的程序設計,也沒有不讓程序退出的建議,注意:程序要結束執行,是由程序邏輯控制的,面向誰也阻止不了這個事實;

補充一下程序等知識:

假設系統啟動起來了,你要打開一個程序,」系統「會從第一行開始執行,到最後一行結束,完事兒;

然後系統又沒事兒了,等著,準備執行別的程序,周而復始;

如果你的程序啟動後在解一個難題,比如說42是什麼意思?它就會一直執行下去,除非找到了答案,它就要退出來,告訴你有答案了,這時,在一直執行的過程中,一找到答案,就會調用exit()這個函數了,顯示出答案,而程序也不用再執行了,退出吧。

從上面你就可以看出來,就算是面向女朋友的程序設計,也需要exit();來結束一個程序的運行;

其實,exit()就是系統為了在解決像42是什麼意思這樣的問題有答案時退出程序的一個方法,必須有用。

沒人邀請,自己來的。


推薦閱讀:

怎樣改造一個有序的鏈表,使其能夠具有高效找到Node在鏈表中index(在鏈表中的第幾個結點)?
計算機圖形學研究生在研究生階段怎麼提升自己實力?
有哪些 C++ 的 JSON 庫比較好呢?
C++為什麼函數參數個數不同還能出錯啊?
依賴C++的情況下該如何選擇做GUI界面的框架?

TAG:編程語言 | 編程 | C編程語言 | C | CC |