方案二:崩潰位址 + map檔案 + cod檔案
由於vc8以後的版本都不再支援map檔案中產生**行資訊,因此我們尋找另一種定位方式:cod檔案。
1、cod檔案
cod檔案是乙個包含了彙編碼、二進位制機器碼和源**對應資訊的檔案,每乙個cpp都對應乙個cod檔案。通過這個檔案,我們可以非常方便地進行定位。
在vc6中生成cod檔案的設定方式為:project settings -> c/c++,在 category 中選 listing files,在 listing file type 組合框中選 assembly,machine code,and source。在vc8中生成cod檔案的設定方式為:project properties -> c/c++ -> output files -> assembler output 項,選擇 assembly,machine code,and source(/facs)。
2、定位崩潰行
下面通過舉例進行說明。現在我有乙個基於對話方塊的mfc應用程式crashtest,在ccrashtestdlg::oninitdialog函式中寫入導致crash的**語句(第99行),原始檔如下:
根據崩潰位址(0x004012a3)以及map檔案(定位片段如下),定位crash函式為oninitdialog;並且我們可以很容易地計算出崩潰位址相對於崩潰函式的偏移量為 0x004012a3 - 0x004011e0 = 0xc3。
再來看看crashtestdlg.cod檔案,我們根據檔案中原始碼資訊找到oninitdialog函式資訊片段:
可以看到中第一行為oninitdialog函式彙編**的起始行;找到「int * p = null;」這一句原始碼,其前面的98表示這行**在原始檔中的行號,下面的000c1表示相對於函式開始位置的偏移量,後面的「33 c0」為機器碼,「xor eax,eax」為彙編碼。那麼我們根據前面算出來的偏移量0xc3,找到對應出錯的語句為99行:「*p = 5;」。
總結一下定位步驟:
1) 根據公式崩潰語句在函式中偏移位址 = 崩潰位址 - 崩潰函式位址計算出偏移量x;
2) 根據公式崩潰語句在cod檔案中位址 = 崩潰函式在cod檔案中位址 + x計算出位址y。其中崩潰函式在cod檔案中位址為cod檔案中函式起始括號「{」後面表明的位址,一般情況下為0x0000;
3) 根據y在cod檔案中找到對應**行。
ok,方案二介紹完了。這種方法最大的好處是沒有vc開發環境版本限制,而且cod檔案裡面包含的資訊更加豐富,不但可以幫助我們定位crash,還能幫我們分析很多東西。當然,這也導致編譯生成了很多資訊檔案。
除錯Release發布版程式的Crash錯誤(一)
非常感謝作者提供了乙個系統的解決方案 在windows平台下用c 開發應用程式,最不想見到的情況恐怕就是程式崩潰,而要想解決引起問題的bug,最困難的應該就是除錯release版本了。因為release版本來就少了很多除錯資訊,更何況一般都是發布出去由使用者使用,crash的現場很難保留和重現。本文...
除錯Release發布版程式的Crash錯誤(一)
在windows平台下用c 開發應用程式,最不想見到的情況恐怕就是程式崩潰,而要想解決引起問題的bug,最困難的應該就是除錯release版本 了。因為release版本來就少了很多除錯資訊,更何況一般都是發布出去由使用者使用,crash的現場很難保留和重現。本文將給出幾個解決方案,完成對 rele...
除錯Release發布版程式的Crash錯誤(五)
當我們把自己的release版本程式發布出去以後,一般都是在使用者的機器上執行。這種情況下,對於第四種方案,因為需要pdb檔案才能夠正確生成 堆疊呼叫的函式行號及 行號,因此方案四隻適用於本地release版的除錯,否則只能生成不完整的堆疊資訊。對於前三種方案,其實只需要使用者告知崩潰 位址,然後在...