簡單的定位到程序崩潰地點的方法



事例程序

2k以上的操作系統,微軟提供了一種新的功能Online Crash Analysis,簡稱OCA,就是當程序崩潰的時候我們看到的的那個對話框,問你是否把崩潰的一些信息發送到微軟,各個軟件廠商可以從微軟那裏根據收集到的程序版本和出錯的地址等信息來完善自己的程序。

如果你手頭什麼小工具都沒有的情況下,下面這個方法可以很快的手工定位到出錯地點。

點擊“請單擊此處”,可以看到詳細的信息。


其中AppName是出錯程序的exe文件名,AppVer是exe文件版本,ModName是此exe文件調用的崩潰模塊的名稱,ModVer是版本,最重要的就是Offset了,是崩潰的地址。

找到與出錯版本程序對應的代碼版本,在工程選項設置裏Link->General勾上Generate mapfile,創建出一個與編譯結果同名的map文件;並且在C/C++->Listing Files->Listing file type中選擇Assembly,Machine Code,and Source一項,這樣會爲每個cpp文件創建出一個同名的cod文件。

編譯出來以後我們就可以根據程序崩潰的地址開始一步步的尋找源頭了。

事例程序是我用VC創建的一個對話框工程,然後改寫了下面函數,下載後把後綴名改爲rar

void CAboutDlg::OnOK() 
{
    
void* p = NULL;

    memcpy(p, 
this1024);
    
    CDialog::OnOK();
}

這樣點擊關於對話框上ok鍵就會崩潰了。

在示例程序中崩潰的地址是0x000012ad,先用一個文本編輯器打開map文件,在最上面可以看到一行Preferred load address is 00400000,代表程序的運行空間的起始地址爲0x00400000,那麼實際崩潰的地址就應該是0x00400000 + 0x000012ad = 0x004012ad,往下看map文件,有這麼兩行:

0001:000002a0       ?OnOK@CAboutDlg@@MAEXXZ    004012a0 f   1.obj
0001:000002c0       ??3CObject@@SGXPAX@Z       004012c0 f i 1.obj

第一個模塊後面的地址是0x004012a0,第二個模塊後面的地址是0x004012c0,而0x004012ad落在了這兩個模塊中間,那就說明崩潰的地址在第一行的代碼範圍內。

最後面的1.obj揭示了崩潰的具體文件,找到對應的1.cod文件,用文本編輯器打開,查找?OnOK@CAboutDlg@@MAEXXZ,能查找到多處,其中有一處?OnOK@CAboutDlg@@MAEXXZ PROC NEAR字樣的就是此函數的起始處,下面用機器碼、彙編和源代碼描述了代碼的細節。

這個函數的起始地址是0x004012a0,而崩潰的地址是0x004012ad,這兩個相減,得到了崩潰的地址相對於函數起始的偏移地址0xd,看每一行彙編代碼最前面的數字,就是偏移地址,找到0000d,後面的彙編就是出錯的指令行,而上面的源代碼就是出錯的代碼行。

這種方法一般用來處理OCA的bug,或者對付一些debug班沒問題但是release板有問題的疑難雜症,但是如果ModName定位不在自己的程序裏就沒有辦法了,那就有可能是因爲自己程序裏出了一些問題,但是沒有崩潰,而代碼走到了windows自身的模塊中才受到影響崩潰了。

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章