在release下尋找程式崩潰原因

2021-06-08 20:35:17 字數 1591 閱讀 4679

在windows平台下用c++開發應用程式,最不想見到的情況恐怕就是程式崩潰,而要想解決引起問題的bug,最困難的應該就是除錯release版本了。因為release版本來就少了很多除錯資訊,更何況一般都是發布出去由使用者使用,crash的現場很難保留和重現。本文將給出幾個解決方案,完成對release版應用程式crash錯誤的除錯。(本文只討論windows平台msvc環境下的除錯,對於其他平台和開發環境沒有關注,請大家自己借鑑和嘗試。)

+ map檔案

這種方案只能對vc7以前的版本開發的程式使用。 

1、崩潰位址

上面第2張圖中畫紅線的值為crash的**偏移位址,第3張圖為即crash絕對位址;一般引起crash的原因多為記憶體操作錯誤,我們用這兩個位址和map檔案就能定位出錯的**行。

2、map檔案

map檔案是記錄應用程式資訊的檔案(文字檔案),裡面大概包含了程式的全域性符號、原始碼模組名、原始碼檔案和行號等資訊,而這些資訊能夠幫助我們定位出錯的**行。

怎樣生成map檔案呢?以vc6為例,在 project settings -> c/c++ -> debug info中,選擇 line numbers only ;在 project settings -> link 中,選擇 generate mapfile項,並在project options 裡面輸入 /mapinfo:lines 和 /mapinfo:exports,重新編譯程式就會生成.map檔案。

/zi— 表示生成pdb除錯資訊;

/map[:filename]— 表示生成map檔名;

/mapinfo:exports— 表示生成的map檔案中加入exported functions(生成dll檔案時);

/mapinfo:lines— 表示生成的map檔案中加入**行資訊。

由於/mapinfo:lines選項在vc8以後的版本中不再支援,因此通過map檔案中的資訊和crash位址定位出錯**行就比較困難了,所以這種方案只能在vc7及以前的版本中使用。

乙個map檔案片段示例如下: 

圖中rva+base列的位址為該行函式對應的函式絕對位址,address列中冒號後面的位址為函式相對偏移位址。 

3、定位crash**

有了上面的介紹,定位crash**就很簡單了。用下面的公式來進行定位:

崩潰行偏移 = 崩潰位址 - 崩潰函式絕對位址 + 函式相對偏移

我們首先根據崩潰位址(絕對位址),按照找到第2張圖中rva+base列的位址找到發生崩潰的函式(即崩潰位址大於該函式行的rva+base位址且小於下個函式的位址),然後找到該行對應的函式相對偏移位址,帶入公式中,就得到了崩潰行偏移,該值表示崩潰行的**相對於**所在函式的偏移量。用該值去與第3張圖中對應函式冒號後面的偏移量去比較,最接近的值前面的那個十進位制數即為**所在函式中的行號。

ok,到此我們已經成功找到了崩潰的**行,只不過這種方法還是比較費力,並且限制比較多,我們看看下面的方案。

Release下輕鬆除錯程式。

在開發過程中經常會碰到一寫莫名其妙的情況發生,比如明明在debug下編譯執行一切正常,但是在release下編譯執行總是會出錯。這個時候多希望release下可以除錯程式啊。之前我一直以為這是不可能,後來才發現,微軟的vs工具為我們提供了這樣乙個功能,平時大家可能沒有注意到。我們只需要做一些簡單的設...

Linux下的C 程式崩潰時列印崩潰資訊

在某些極端情況下,原本正常執行的程式發生了崩潰。這時候想通過除錯是很難發現出錯的地方的,所以在崩潰時列印出錯點的呼叫堆疊是十分有必要的。使用的命令 catchsegv program args 例如 我們的程式是test,則可在控制台輸入 catchsegv test 如果使用gcc g 編譯tes...

eclipse在Centos下崩潰的問題

我在使用eclipse有崩潰的現象,我的eclipse版本是luna,上網上有給出如下解決辦法 在centos 6下安裝linux後,可能會有以下的崩潰訊息 eclipse cairo misc.c 380 cairo operator bounded by source assertion not...