一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

調(diào)試經(jīng)驗(yàn)談-根據(jù)crashdump查找bug

 MarkG 2011-01-13

很多時(shí)候,我們不知道如何重現(xiàn)一個(gè)crash問題,只有一些log或者dump,拿到一個(gè)這樣的crash的問題,并不知道是什么原因,怎么樣來慢慢分析,這篇文章就舉了一個(gè)現(xiàn)實(shí)的例子,看看怎么查找一個(gè)crash問題的原因。

這個(gè)是我們軟件發(fā)生的一次崩潰,只在客戶的環(huán)境上發(fā)生,沒有人知道在實(shí)驗(yàn)室里怎么重現(xiàn),好在客戶那邊給出了windows的dump文件,這樣就可以很容易的查看當(dāng)時(shí)的案發(fā)現(xiàn)場了。

用windbg打開dump文件,打開匯編窗口,點(diǎn)擊調(diào)用堆棧最上面的函數(shù),就可以看到如下匯編代碼

2e252013 51              push    ecx
2e252014 53              push    ebx
2e252015 57              push    edi
2e252016 8bf9            mov     edi,ecx
2e252018 33db            xor     ebx,ebx
2e25201a 395f04          cmp     dword ptr [edi+4],ebx
2e25201d 7454            je      nqp+0x22073 (2e252073)
2e25201f 66395f14        cmp     word ptr [edi+14h],bx
2e252023 763c            jbe     nqp+0x22061 (2e252061)
2e252025 895dfc          mov     dword ptr [ebp-4],ebx
2e252028 56              push    esi
2e252029 8da42400000000  lea     esp,[esp]
2e252030 8b7704          mov     esi,dword ptr [edi+4]
2e252033 0375fc          add     esi,dword ptr [ebp-4]
2e252036 837e0800        cmp     dword ptr [esi+8],0  ds:0023:613d634e=????????  <<-----軟件在這里就崩潰了

通過調(diào)用堆棧,我們可以找到對應(yīng)的函數(shù)的源碼

void HTMLelement:: ResetPriv()
{
    if (i_pAttributeList) {
        for (int i = 0; i < i_totAttrs; i++) {
            GetAttributeEntry(i)->Reset();
        } 
    }   
}

可以看出來 是在cmp     dword ptr [esi+8],0 的時(shí)候出了異常,這個(gè)指令能出的異常,也就是 [esi+8]不能讀,這說明 esi+8這個(gè)地址錯(cuò)了,但是為啥會(huì)錯(cuò)呢,只能是esi的值不對。先看看esi是多少,在命令窗口 輸入 r esi

0:036> r esi
Last set context:
esi=613d6346

這個(gè)613d6346 顯然是不可訪問的內(nèi)存。所以,我們就需要看看esi是哪里來的。一行行的往上看:

add     esi,dword ptr [ebp-4]

這句把ebp-4里面的數(shù)加到esi上,那我們需要看看ebp-4是多少了,在命令窗口里面輸入 dd ebp-4

0:036> dd ebp-4
32e3cc10  00000000 32e3cc24 2e252966 32e47284
32e3cc20  32e47218 32e3cc44 2e252e24 32e47284
32e3cc30  00000000 00000001 32e47218 32e47218
32e3cc40  00000000 32e3e9fc 2e3abbd6 32e3e960
32e3cc50  00000000 00000000 00000001 32e3f8f0
32e3cc60  00000000 2e462e8c 00000000 32e3cc84
32e3cc70  00000001 016edda8 32e3cf5c 03434cf8
32e3cc80  034348f8 32e3cc90 60001780 016edda8

可見 ebp-4是0,這很正常,這個(gè)ebp-4是個(gè)局部變量i,其實(shí)就是個(gè)數(shù)組的下標(biāo),0不像是個(gè)越界的值,那么就需要繼續(xù)往前看

mov     esi,dword ptr [edi+4]

esi的值是來自edi+4,那我們來看看edi+4是啥

0:036> dd edi
32e3e960  32257974 613d6346 00000075 00000042
32e3e970  00000002 00000002 00000000 00000000
32e3e980  32e3e9a0 00000000 00000000 00000019
32e3e990  00000002 00000000 00000000 00000000
32e3e9a0  32e3e960 00000000 00000000 0000006e
可見這個(gè)值就是613d6346,就是esi的值,那就說明 這個(gè)內(nèi)存里面的值有問題,出錯(cuò)的可能有兩個(gè),一種可能是這個(gè)內(nèi)存的值不對,另一種可能是是edi的值不對,導(dǎo)致取值取錯(cuò)了地方。跟蹤edi還是容易一點(diǎn),所以我們繼續(xù)往上看edi的值是哪里來的。

2e252016 8bf9            mov     edi,ecx

這個(gè)是函數(shù)的開頭,我們知道ecx放的就是對象的地址,也就是this,說明edi里面就是this,這就說明edi出錯(cuò)的可能比較小了,除非上面 函數(shù)傳值的時(shí)候就傳錯(cuò)了,看了一下源碼,這個(gè)HTMLelement的地址應(yīng)該沒啥太大機(jī)會(huì)出錯(cuò)。這里不是說完全排除,但是進(jìn)一步跟蹤的代價(jià)比較大了,所 以我們先放一下,看另外一個(gè)可能。那就是這個(gè)對象里面的內(nèi)容出錯(cuò)了。

越界的問題往往是數(shù)組越界,而字符串是最容易越界的,我們來看看這個(gè)會(huì)是啥字符,輸入 dc edi 看看

:036> dc edi
32e3e960  32257974 613d6346 00000075 00000042  ty%2Fc=au...B...
32e3e970  00000002 00000002 00000000 00000000  ................
32e3e980  32e3e9a0 00000000 00000000 00000019  ...2............
32e3e990  00000002 00000000 00000000 00000000  ................
32e3e9a0  32e3e960 00000000 00000000 0000006e  `..2........n...
32e3e9b0  00000002 00000000 00000000 00000000  ................
32e3e9c0  2e46beb4 00000000 3607274c 00000091  ..F.....L'.6....
32e3e9d0  32e3e9a0 00000000 00000000 00000033  ...2........3...

很明顯這里應(yīng)該是是個(gè)指針的地方,居然看起來像個(gè)字符串了,往前看看完整的字符串是啥

0:036> dc edi-128 edi+16
32e3e838  00000000 00000000 00000000 00000000  ................
32e3e848  00000000 00000001 00000001 ffffffff  ................
32e3e858  2e2f2e2e 64242f2e 75616665 6976746c  ../../$defaultvi
32e3e868  372f7765 45314243 43443944 43463944  ew/7CB1ED9DCD9FC
32e3e878  38424145 36353235 30334337 32453630  EAB852567C3006E2
32e3e888  2f454244 65704f3f 636f446e 6e656d75  DBE/?OpenDocumen
32e3e898  72502674 74655365 6c656946 683d7364  t&PreSetFields=h
32e3e8a8  7465535f 64616552 6e656353 5f683b65  _SetReadScene;h_
32e3e8b8  75636553 79746972 626d654d 6e497265  SecurityMemberIn
32e3e8c8  682c6f66 6d654d5f 4e726562 3b656d61  fo,h_MemberName;
32e3e8d8  4a3d6e63 61696c75 3032256e 73726143  cn=Julian%20Cars
32e3e8e8  32256e6f 3d756f46 69737542 7373656e  on%2Fou=Business
32e3e8f8  50303225 6e6e616c 25676e69 6e613032  %20Planning%20an
32e3e908  30322564 6f736552 65637275 46322573  d%20Resources%2F
32e3e918  533d756f 65647574 3225746e 646e6130  ou=Student%20and
32e3e928  43303225 756d6d6f 7974696e 53303225  %20Community%20S
32e3e938  69767265 25736563 756f4632 6174533d  ervices%2Fou=Sta
32e3e948  32256666 4d3d6f46 73616e6f 30322568  ff%2Fo=Monash%20
32e3e958  76696e55 69737265 32257974 613d6346  University%2Fc=a
32e3e968  00000075 00000042 00000002 00000002  u...B...........

看來前面是個(gè)很長的字符串,數(shù)數(shù)看,從字符串開始的地方 32e3e858 算,有270多個(gè)字符,估計(jì)有某個(gè)地方定義了個(gè)256的緩存區(qū),然后沒做檢查,就把后面的棧上的內(nèi)存給覆蓋了,繼續(xù)看stack,看看這個(gè)字符數(shù)組是屬于哪個(gè)函數(shù)的棧幀。k可以看函數(shù)調(diào)用棧

0:036> k
  *** Stack trace for last set context - .thread/.cxr resets it
ChildEBP RetAddr  
WARNING: Stack unwind information not available. Following frames may be wrong.
32e3cc14 2e252966 nqp+0x22036
32e3cc24 2e252e24 nqp+0x22966
32e3cc44 2e3abbd6 nqp+0x22e24
32e3e9fc 2e3ae8d7 nqp+0x17bbd6
32e3eb40 2e3ace45 nqp+0x17e8d7
32e3eb84 2e3c9823 nqp+0x17ce45
32e3ebbc 2e2fb73b nqp+0x199823
32e3ebcc 2e301e22 nqp+0xcb73b
32e3ffe4 2e318255 nqp+0xd1e22
32e402a8 2e271b68 nqp+0xe8255
32e42c78 2e27236a nqp+0x41b68
32e42cc0 600bbf1a nqp+0x4236a

因?yàn)槲椰F(xiàn)在沒有當(dāng)時(shí)那個(gè)版本的pdb,所以顯示不了具體的函數(shù),有pdb的話,可以看到函數(shù)名字,我們可以看出來32e3e858 是屬于下面這個(gè)函數(shù)調(diào)用的棧上的

32e3e9fc 2e3ae8d7 nqp+0x17bbd6

在有symbol的情況下,就可以知道是哪個(gè)函數(shù)了,在這個(gè)函數(shù)里面,找到了這樣的語句。

                char memberDocURL[MAX_PATH+1] = "javascript:void(0);";

                ........

                URLencodedString.Copy(dn);
                huURL.URLencode(&URLencodedString);
                strcat(memberDocURL, URLencodedString);

在棧上開了個(gè)MAX_PATH+1的數(shù)組,這里MAX_PATH是260,然后一系列操作,都是靠strcat來做的,dn這個(gè)字符串如果很長,就像上面顯示的那樣,URLencodedString也會(huì)很長,就會(huì)導(dǎo)致寫越界了。把后面的對象給覆蓋了。

到這里,原因就找到了。典型的字符串操作不小心導(dǎo)致緩存區(qū)溢出。

總結(jié)一下,對于這種不可重現(xiàn)的crash問題,就是要從crash的地方入手,看看哪個(gè)數(shù)據(jù)不對,順藤摸瓜,一點(diǎn)點(diǎn)往前面排查。windbg是個(gè)很強(qiáng)大的調(diào)試工具,特別是分析這種只有dump,沒法重現(xiàn)的問題,非常有用。

    本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    97人妻人人揉人人躁人人| 亚洲国产av国产av| 成年女人下边潮喷毛片免费| 黑丝国产精品一区二区| 国产欧美日韩精品一区二区| 日韩人妻中文字幕精品| 欧美成人黄色一级视频| 久久国产精品热爱视频| 久久99一本色道亚洲精品| 亚洲精品欧美精品日韩精品| 少妇人妻一级片一区二区三区| 国产盗摄精品一区二区视频| 国产一区欧美一区日本道| 自拍偷拍一区二区三区| 国产精品午夜福利在线观看| 亚洲最新av在线观看| 亚洲天堂精品在线视频| 亚洲精品福利视频在线观看| 国产免费自拍黄片免费看| 人妻少妇久久中文字幕久久| 日韩中文字幕视频在线高清版| 欧美日韩国产的另类视频| 国产亚洲二区精品美女久久| 中文字幕亚洲精品乱码加勒比| 99久久精品午夜一区| 国产色第一区不卡高清| 好吊日在线观看免费视频| 国产精品欧美激情在线| 激情丁香激情五月婷婷| 大香蕉久久精品一区二区字幕 | 风间中文字幕亚洲一区| 高清一区二区三区四区五区| 日韩欧美国产精品中文字幕| 国产精品一区二区三区欧美| 99久久精品视频一区二区| 色婷婷国产熟妇人妻露脸| 欧美极品欧美精品欧美| 大香蕉伊人一区二区三区| 日本午夜乱色视频在线观看| 在线视频免费看你懂的| 中文字幕免费观看亚洲视频|