在編寫unix程式的時候,常常會出現一些錯誤,而最毀滅性的就是程序直接down掉
程序意外退出會給使用者帶來很多負面影響
同時如果除錯和日誌檔案不夠完善的話,查起錯來相當麻煩,再加上使用者環境和我們的開發環境不一樣,當你回過頭來改這個錯誤,如果日誌不夠完善,甚至需要在使用者的環境下復現錯誤,這基本上是不可能的,尤其是你的**要跑一段時間才能復現錯誤
我剛進公司的時候寫了一些簡單的應用程式,為快速實現功能同時由於缺少liunx環境下使用者程式開發的經驗,沒有做好除錯的工作,在開發環境下除錯甚至是通過列印資訊到終端來完成的,雖然最後在公司測試沒什麼問題,但是放到使用者那裡就會出錯,而且還找不到原因,最後也搞不明白是自己程式的錯誤還是其他原因導致的
在吃了幾次自己的虧以後,為每次都乖乖的把日誌完善
下面總結以下程序會意外退出的幾種情況
一.程序的退出
apue 第7章第一頁列出了8種程序退出的方式
其中5種是由我們的**控制,通過呼叫退出的函式正常退出,這是我們程式中顯示的退出,是容易查詢也是容易控制的
另外3種退出是 異常退出,也是我們不願看到,隱式的退出,分別是
1.呼叫abort
2.接收到乙個訊號並終止
3.最後乙個執行緒對取消執行緒作出相應
對於abort,我們理解為人為製造異常讓程式退出,其實就是製造sigabrt訊號給程序,程序不理會對這個訊號的捕獲忽略,捕獲這個訊號純粹只是為了做一些清理工作,在訊號處理函式中不做退出的話,訊號處理函式返回時,程序會自己退出
第二種情況是我們最常見的意外退出的方式,待會仔細說
最後一種,在程序中的乙個執行緒中錯誤呼叫exit(),_exit,_exit,那麼整個程序都會終止掉,或者最後乙個執行緒的取消訊號非同步到來(訊號處於未決狀態),而取消並沒有被設定為無效,那麼執行緒就會被取消,整個程序也就消失了
二.導致程序意外退出的情況
導致意外退出的情況一般是兩種
1.程序收到乙個訊號導致異常退出
2.你的**有問題,執行異常導致退出(最常見的就是段錯誤,雖然也是乙個訊號)
首先分析訊號:
1.訊號從**來:程序自己產生或者作業系統核心發出
2.訊號處理 :不同的訊號採取不同的處理方法,有:
終止程序
終止程序並產生core dump檔案
忽略訊號
暫停程式
重新排程(取消暫停)
實際上我們要處理的主要是前兩種情況
處理訊號:
訊號會終止程序是因為當程序收到訊號如果我們不捕獲這個訊號,大多數的訊號採取的預設操作都是終止程序,除非我們捕獲這個訊號執行使用者自定義的處理函式
如果我們能正確捕捉訊號而且明確這個訊號不會對我們的系統造成影響,將這個訊號忽略掉,那麼就減少了我們程式意外終止的機率
下面簡單說說編寫**的錯誤
這類錯誤其實是不難被發現的,因為這類錯誤導致的結果應該是比較顯式的
比如說除法運算錯誤的除數
比如說段錯誤,在測試階段不難被發現
執行緒中呼叫exit()來退出執行緒
還有就是記憶體洩漏帶來的問題也是比較明顯的
程序中錯誤的休眠
三.避免程序意外退出
1.一般來說我們是無需處理訊號,訊號作為程序間通訊的一種手段,自然是有它的作用
2.確保程式設計中不要出現非法的操作
3.對一些訊號捕獲和忽略 常見的比如 sigpipe
4.最好退出前做一些清理工作保證就算意外退出也不會對系統造成影響,比如釋放記憶體,刪除臨時檔案
四.問題
程序退出大多是由於訊號的關係,而哪些訊號該捕獲忽略,那些訊號不能忽略是個頭疼的問題,另外程序的退出也可能會是一些看似正常的退出,比如**中的系統呼叫被訊號中斷錯誤的返回乙個錯誤號,而不加分析的將程序退出也是我們不願看到的
五.做好除錯與定位
好了,回到我們一開始提出的問題就是認真將每乙個可能的出錯都記錄到日誌檔案中,這樣我們在出錯的時候也不至於一點頭緒都沒有,
還有就是使用gdb除錯也是定位錯誤的好方法
《unix高階環境程式設計》程序環境 程序終止
當核心執行c程式時 使用乙個exec函式執行 在呼叫mian函式前先呼叫乙個特殊的啟動例程。可執行程式檔案將此啟動例程指定為程式的起始位址。下面是c程式啟動和終止的流程,由圖中可以知道,程序的終止根據不同的函式呼叫是不一樣的,其中 exit和 exit函式是終止程序直接進入核心,exit函式則先執行...
程序退出(UNIX環境高階程式設計筆記)
如果父程序fork了乙個子程序,父程序先於子程序終止,子程序的父程序將改為init程序。其大致操作是 在乙個程序終止時,核心諸葛檢查所有活動程序,以判斷它是否是正要終止程序的子程序,如果是,則該程序的父程序id就更改為1。核心為每個終止子程序儲存了一定量的資訊,當終止程序的父程序通過wait或wai...
oracle錯誤 1067程序意外終止
oracle錯誤 1067程序意外終止 我oracle安裝完了之後可以執行的 過了一段時間不可以了,就上網找了一下,原來是自己的ip已經改變。我一直使用ip位址的。將d oracle product 10.2.0 db 1 network admin下面的檔案listener.ora和tnsname...