2015-04-04 51 views
1

我的問題是:用C++覆蓋崩潰

有沒有辦法在程序發生崩潰時調用函數或做其他工作。

具體而言,我目前正在使用的代碼在非常大的輸入上出現「段錯誤」。這意味着我正在訪問一些不可用的\未分配內存部分。顯示每一步都太難理解了,所以我想要檢測什麼時候跨越了我的界限。

那麼這怎麼可能呢?

+1

爲什麼不按順序運行下的valgrind代碼中查找和修復bug( s)? – 2015-04-04 09:53:30

+2

「我想要檢測什麼時候越過我的界限」與「在發生崩潰時調用函數或做其他工作」無關。使用調試器對前者有好處。從C++的角度來看,後者是一般未定義行爲機制的功能,在這種制度下,C++標準沒有任何保證。不過,對於正常的終止,包括未捕獲的異常,你有'std :: terminate'。 – 2015-04-04 10:13:52

+0

是的(我看到它是一種unix) - 編譯時啓用了調試(cc -g ...),然後使用gdb:gdb --args ./program 運行,然後運行 – 2015-04-04 13:30:04

回答

1

它是操作系統和具體實現。實際上也取決於編譯器和優化標誌。

很可能,你已經打了一些undefined behavior

也許valgrind應該是一個非常有用的工具。

如果在Linux上,閱讀core(5) & proc(5) & signal(7)。您可能會在系統範圍內設置您的/proc/sys/kernel/core_pattern僞文件來啓動核心轉儲中的某個外部程序或腳本(可能啓動一個調試器)。

你甚至可以在處理器和操作系統,系統特定的方式處理SIGSEGV信號。但我不建議這樣做。見this & that 答案更多。

在Linux上,系統調用(在syscalls(2)上市)幾乎可以將信號處理程序內調用的唯一功能(更確切地說,它是在signal(7)而已提到異步信號安全功能)。但是很多的庫函數(包括malloc & printffprintfdlopen等等)都是內部信號處理程序被禁止。

1

如果您編譯與調試符號代碼,你應該能夠在碰撞發生時要麼加載一個核心文件到您的調試器和/或附加一個調試器。

通常情況下,你可以告訴崩潰的位置發生了什麼。你解除引用空指針嗎?你解除了一個無效指針嗎?第二個比第一個更難調試(通常意味着內存損壞)。一個用於內存損壞的有用工具,尤其是在錯誤是可重複的情況下使用,就是放置「觀察點」,只要某個特定的內存位置(即導致崩潰的指針)發生改變,就會導致調試器暫停。這可以讓你看到什麼改寫了你的指針。

1

你確實需要一個調試器。但是,爲了回答一個問題,原爲未來的搜索:

是,在UNIX你可以只處理與通常的信號處理程序的SEGV信號。 SIGSEGV的編號爲13.有關如何處理信號,請參閱this

請注意系統對信號處理程序 (例如系統調用被禁止,包括IO)可以做的限制有限制。 此外,如果訪問您的程序數據等待它可能已損壞。你的程序會在信號處理程序之後繼續工作,但它很可能會很快進入另一個錯誤。

我不會電子書籍這樣做在生產代碼,但我覺得這個功能是「Unix的」提夠的SO

+0

syscalls被允許(在Linux上)信號處理程序。但是很多功能都被禁止。看到我的答案。 – 2015-04-08 17:36:32