非常感謝作者提供了乙個系統的解決方案
在windows平台下用c++開發應用程式,最不想見到的情況恐怕就是程式崩潰,而要想解決引起問題的bug,最困難的應該就是除錯release版本了。因為release版本來就少了很多除錯資訊,更何況一般都是發布出去由使用者使用,crash的現場很難保留和重現。本文將給出幾個解決方案,完成對release版應用程式crash錯誤的除錯。(本文只討論windows平台msvc環境下的除錯,對於其他平台和開發環境沒有關注,請大家自己借鑑和嘗試。)
+ map檔案
這種方案只能對vc7以前的版本開發的程式使用。
1、崩潰位址
所謂崩潰位址就是引起程式崩潰的記憶體位址,在winxp下應用程式crash的對話方塊如下圖:
上面第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發布版程式的Crash錯誤(一)
在windows平台下用c 開發應用程式,最不想見到的情況恐怕就是程式崩潰,而要想解決引起問題的bug,最困難的應該就是除錯release版本 了。因為release版本來就少了很多除錯資訊,更何況一般都是發布出去由使用者使用,crash的現場很難保留和重現。本文將給出幾個解決方案,完成對 rele...
除錯Release發布版程式的Crash錯誤(五)
當我們把自己的release版本程式發布出去以後,一般都是在使用者的機器上執行。這種情況下,對於第四種方案,因為需要pdb檔案才能夠正確生成 堆疊呼叫的函式行號及 行號,因此方案四隻適用於本地release版的除錯,否則只能生成不完整的堆疊資訊。對於前三種方案,其實只需要使用者告知崩潰 位址,然後在...
除錯Release發布版程式的Crash錯誤(二)
方案二 崩潰位址 map檔案 cod檔案 由於vc8以後的版本都不再支援map檔案中產生 行資訊,因此我們尋找另一種定位方式 cod檔案。1 cod檔案 cod檔案是乙個包含了彙編碼 二進位制機器碼和源 對應資訊的檔案,每乙個cpp都對應乙個cod檔案。通過這個檔案,我們可以非常方便地進行定位。在v...