除錯Release發布版程式的Crash錯誤(一)

2021-05-26 09:16:34 字數 2288 閱讀 8431

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

+ map檔案

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

1、崩潰位址

所謂崩潰位址就是引起程式崩潰的記憶體位址,在

winxp

下應用程式

crash

的對話方塊如下圖:

上面第2張圖中畫紅線的值為

crash

的**偏移位址,第

3張圖為即

crash

絕對位址;一般引起

crash

的原因多為記憶體操作錯誤,我們用這兩個位址和

map檔案就能定位出錯的**行。

2map檔案

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檔案片段示例如下:

列的位址為該行函式對應的函式絕對位址,

address

列中冒號後面的位址為函式相對偏移位址。

3、定位crash**

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

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

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

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

除錯Release發布版程式的Crash錯誤(一)

非常感謝作者提供了乙個系統的解決方案 在windows平台下用c 開發應用程式,最不想見到的情況恐怕就是程式崩潰,而要想解決引起問題的bug,最困難的應該就是除錯release版本了。因為release版本來就少了很多除錯資訊,更何況一般都是發布出去由使用者使用,crash的現場很難保留和重現。本文...

除錯Release發布版程式的Crash錯誤(五)

當我們把自己的release版本程式發布出去以後,一般都是在使用者的機器上執行。這種情況下,對於第四種方案,因為需要pdb檔案才能夠正確生成 堆疊呼叫的函式行號及 行號,因此方案四隻適用於本地release版的除錯,否則只能生成不完整的堆疊資訊。對於前三種方案,其實只需要使用者告知崩潰 位址,然後在...

除錯Release發布版程式的Crash錯誤(二)

方案二 崩潰位址 map檔案 cod檔案 由於vc8以後的版本都不再支援map檔案中產生 行資訊,因此我們尋找另一種定位方式 cod檔案。1 cod檔案 cod檔案是乙個包含了彙編碼 二進位制機器碼和源 對應資訊的檔案,每乙個cpp都對應乙個cod檔案。通過這個檔案,我們可以非常方便地進行定位。在v...