最近的工程在用vs2005进行调试, 现在可以Attach到Release版带调试符号的目标程序进行调试, 但是在非开发机上就没这条件了.

看了以下几篇资料, 做个实验.

http://www.codeproject.com/KB/debug/mapfile.aspx?msg=1315494
Finding crash information using the MAP file <vc6版好使>

http://www.cppblog.com/Walker/articles/146153.html
调试Release发布版程序的Crash错误 (转)<这个资料说全了, 可以在vs2005中做事后调试>

自己写了一个demo, 进行了验证, 可行. 但是没有实战性, 准备找个实际的程序来验证.

我在CodeProject 找了一个扫雷程序:

http://www.codeproject.com/KB/cpp/Mine4Edu.aspx
<<Adapted WinMine Source for Teaching Win32 API Programming>>

本来想搞个数组越界的错误,人家的程序写的太坚固了,弄了数组越界操作,也不报错。

只好弄了一个除零错~

编译选项是Release版不优化带调试符号,为了根据转储信息定位到代码中的行, 设置了MAPInfo和COD文件.

在Win7上程序报错是有崩溃对话框的, 但是我的WinXp上崩溃对话框没出来,只有一个报错对话框, 没有转储信息.

安装系统自带的drwtsn32.exe作为调试工具.

http://support.microsoft.com/kb/188296/zh-cn
<<如何禁用或启用 Windows 的 Dr. Watson>>

默认调试器的注册表备份

Windows Registry Editor Version 5.00[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug]
"Auto"="1"
"Debugger"="drwtsn32 -p %ld -e %ld -g"

设置华生医生转储选项

再运行程序时,程序报错后,直接崩溃消失了。到那时,就可以从非开发机(大部分情况是客户现场)拿到转储信息转到开发机进行分析.

如果drwtsn32.exe设置了"视觉通知", 当程序报错时,会有转储提示对话框弹出.如果错误不是每次必现或在客户现场运行不用设置"视觉通知"选项.

如果不设置 "视觉通知", 程序报错后,直接退出了.这时可以去取程序报错时的转储信息。

将转储对话框中的文本全选,复制弄回来.


发生应用程序意外错误:应用程序: D:\LsPrj\subjectResearch\DebugAcrossMap\WinMine4Edu\Unicode Release\WinMine.exe (pid=3528)时间: 2011-12-26 @ 00:51:45.265意外情况编号: c0000094 (除以零)*----> 系统信息 <----*计算机名: 20110616-2328用户名: Administrator终端会话 Id: 0处理器数量: 2处理器类型: x86 Family 6 Model 15 Stepping 6Windows 版本: 5.1当前内部版本号: 2600Service Pack: 3当前类型: Multiprocessor Free注册的单位: 微软中国注册的所有者: 微软用户*----> 任务列表 <----*0 System Process4 System840 smss.exe908 csrss.exe932 winlogon.exe976 services.exe988 lsass.exe
1192 nvsvc32.exe
1252 svchost.exe
1300 svchost.exe252 svchost.exe484 svchost.exe584 svchost.exe620 zhudongfangyu.exe
1620 spoolsv.exe
1852 Explorer.EXE
1932 RTHDCPL.EXE
1948 360Tray.exe
2000 bjcacertd_ft11.exe
2016 vmware-tray.exe
2024 ctfmon.exe128 360sd.exe184 263em.exe288 Snagit32.exe
1728 TSCHelp.exe368 SnagPriv.exe
2004 snagiteditor.exe
1336 GSvr.exe
1384 wdfmgr.exe
1432 vmware-usbarbitrator.exe364 vmnat.exe700 vmnetdhcp.exe
1468 vmware-authd.exe
2168 wmiprvse.exe
2224 vmware-hostd.exe
2568 alg.exe
4000 360rp.exe
4072 firefox.exe
3452 NOTEPAD.EXE
3652 drwtsn32.exe
4080 drwtsn32.exe
3528 WinMine.exe
3036 drwtsn32.exe*----> 模块清单 <----*
(0000000000400000 - 0000000000416000: D:\LsPrj\subjectResearch\DebugAcrossMap\WinMine4Edu\Unicode Release\WinMine.exe
(0000000000920000 - 000000000098d000: C:\Program Files\360\360Safe\safemon\safemon.dll
(000000005d170000 - 000000005d20a000: C:\WINDOWS\system32\comctl32.dll
(0000000062c20000 - 0000000062c29000: C:\WINDOWS\system32\LPK.DLL
(0000000071a10000 - 0000000071a18000: C:\WINDOWS\system32\WS2HELP.dll
(0000000071a20000 - 0000000071a37000: C:\WINDOWS\system32\WS2_32.dll
(0000000073640000 - 000000007366e000: C:\WINDOWS\system32\msctfime.ime
(0000000073fa0000 - 000000007400b000: C:\WINDOWS\system32\USP10.dll
(0000000074680000 - 00000000746cc000: C:\WINDOWS\system32\MSCTF.dll
(0000000075ff0000 - 0000000076055000: C:\WINDOWS\system32\MSVCP60.dll
(0000000076300000 - 000000007631d000: C:\WINDOWS\system32\IMM32.DLL
(00000000765e0000 - 0000000076673000: C:\WINDOWS\system32\CRYPT32.dll
(0000000076680000 - 0000000076726000: C:\WINDOWS\system32\WININET.dll
(0000000076990000 - 0000000076ace000: C:\WINDOWS\system32\ole32.dll
(0000000076bc0000 - 0000000076bcb000: C:\WINDOWS\system32\PSAPI.DLL
(0000000076d70000 - 0000000076d92000: C:\WINDOWS\system32\Apphelp.dll
(0000000076db0000 - 0000000076dc2000: C:\WINDOWS\system32\MSASN1.dll
(00000000770f0000 - 000000007717b000: C:\WINDOWS\system32\OLEAUT32.dll
(0000000077180000 - 0000000077283000: C:\WINDOWS\WinSxS\x86_Microsoft.Windows.Common-Controls_6595b64144ccf1df_6.0.2600.6028_x-ww_61e65202\comctl32.dll
(0000000077bd0000 - 0000000077bd8000: C:\WINDOWS\system32\VERSION.dll
(0000000077be0000 - 0000000077c38000: C:\WINDOWS\system32\msvcrt.dll
(0000000077d10000 - 0000000077da0000: C:\WINDOWS\system32\USER32.dll
(0000000077da0000 - 0000000077e49000: C:\WINDOWS\system32\ADVAPI32.dll
(0000000077e50000 - 0000000077ee3000: C:\WINDOWS\system32\RPCRT4.dll
(0000000077ef0000 - 0000000077f39000: C:\WINDOWS\system32\GDI32.dll
(0000000077f40000 - 0000000077fb6000: C:\WINDOWS\system32\SHLWAPI.dll
(0000000077fc0000 - 0000000077fd1000: C:\WINDOWS\system32\Secur32.dll
(000000007c800000 - 000000007c91e000: C:\WINDOWS\system32\kernel32.dll
(000000007c920000 - 000000007c9b6000: C:\WINDOWS\system32\ntdll.dll
(000000007d590000 - 000000007dd84000: C:\WINDOWS\system32\SHELL32.dll*----> 线程 ID 0xcc0 的状态转储 <----*eax=00000006 ebx=00000000 ecx=0012fd10 edx=00000000 esi=00401fd0 edi=0012fe3c
eip=00401761 esp=0012fd48 ebp=0012fd54 iopl=0         nv up ei pl nz ac po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000216*** ERROR: Module load completed but symbols could not be loaded for D:\LsPrj\subjectResearch\DebugAcrossMap\WinMine4Edu\Unicode Release\WinMine.exe
函数: WinMine00401749 7423             jz      WinMine+0x176e (0040176e)0040174b 6a03             push    0x30040174d 8b450c           mov     eax,[ebp+0xc]00401750 50               push    eax00401751 8b4d08           mov     ecx,[ebp+0x8]00401754 51               push    ecx00401755 e8b6060000       call    WinMine+0x1e10 (00401e10)0040175a 83c40c           add     esp,0xc0040175d 8b4508           mov     eax,[ebp+0x8]00401760 99               cdq
错误 ->00401761 f77d0c           idiv  dword ptr [ebp+0xc] ss:0023:0012fd60=0000000000401764 894508           mov     [ebp+0x8],eax00401767 33c0             xor     eax,eax00401769 e9be000000       jmp     WinMine+0x182c (0040182c)0040176e 8b15e8c84000     mov     edx,[WinMine+0xc8e8 (0040c8e8)]00401774 83c201           add     edx,0x100401777 8915e8c84000     mov     [WinMine+0xc8e8 (0040c8e8)],edx0040177d 8b450c           mov     eax,[ebp+0xc]00401780 50               push    eax00401781 8b4d08           mov     ecx,[ebp+0x8]00401784 51               push    ecx*----> 堆栈反向跟踪 <---*
WARNING: Stack unwind information not available. Following frames may be wrong.
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\WINDOWS\system32\USER32.dll -
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\WINDOWS\system32\kernel32.dll -
ChildEBP RetAddr  Args to Child
0012fd54 0040118f 00000006 00000000 00000006 WinMine+0x1761
0012fd74 004020d7 00000202 00a30012 000000ef WinMine+0x118f
0012fdd4 77d18734 00060648 00000202 00000000 WinMine+0x20d7
0012fe00 77d18816 00401fd0 00060648 00000202 USER32!GetDC+0x6d
0012fe68 77d189cd 00000000 00401fd0 00060648 USER32!GetDC+0x14f
0012fec8 77d18a10 0012ff0c 00000000 0012ff28 USER32!GetWindowLongW+0x127
0012fed8 00401fb4 0012ff0c 00000000 00401fd0 USER32!DispatchMessageW+0xf
0012ff28 00402e78 00400000 00000000 000207e0 WinMine+0x1fb4
0012ffc0 7c817077 0065002e 00650078 7ffdf000 WinMine+0x2e78
0012fff0 00000000 00402ee1 00000000 78746341 kernel32!RegisterWaitForInputIdle+0x49*----> 原始堆栈转储 <----*
000000000012fd48  bc 13 40 00 06 00 00 00 - 00 00 00 00 74 fd 12 00  ..@.........t...
000000000012fd58  8f 11 40 00 06 00 00 00 - 00 00 00 00 06 00 00 00  ..@.............
000000000012fd68  12 00 00 00 a3 00 00 00 - 00 00 00 00 d4 fd 12 00  ................
000000000012fd78  d7 20 40 00 02 02 00 00 - 12 00 a3 00 ef 00 00 00  . @.............
000000000012fd88  68 01 00 00 30 02 00 00 - 48 06 06 00 01 00 00 00  h...0...H.......
000000000012fd98  b0 fd 12 00 01 b4 d2 77 - 58 03 62 00 00 00 00 00  .......wX.b.....
000000000012fda8  00 00 00 00 01 00 00 00 - f4 fd 12 00 d4 13 69 74  ..............it
000000000012fdb8  ee 00 03 00 00 00 00 00 - 01 00 00 00 d9 13 69 74  ..............it
000000000012fdc8  00 00 00 00 00 e0 fd 7f - ac 98 96 db 00 fe 12 00  ................
000000000012fdd8  34 87 d1 77 48 06 06 00 - 02 02 00 00 00 00 00 00  4..wH...........
000000000012fde8  12 00 a3 00 d0 1f 40 00 - cd ab ba dc 00 00 00 00  ......@.........
000000000012fdf8  3c fe 12 00 d0 1f 40 00 - 68 fe 12 00 16 88 d1 77  <.....@.h......w
000000000012fe08  d0 1f 40 00 48 06 06 00 - 02 02 00 00 00 00 00 00  ..@.H...........
000000000012fe18  12 00 a3 00 14 ff 12 00 - 0c ff 12 00 a8 64 67 00  .............dg.
000000000012fe28  14 00 00 00 01 00 00 00 - 00 00 00 00 00 00 00 00  ................
000000000012fe38  10 00 00 00 00 00 00 00 - 8f 04 d4 77 00 00 00 00  ...........w....
000000000012fe48  00 00 00 00 00 00 00 00 - 1c fe 12 00 74 f9 12 00  ............t...
000000000012fe58  b8 fe 12 00 8f 04 d4 77 - 30 88 d1 77 00 00 00 00  .......w0..w....
000000000012fe68  c8 fe 12 00 cd 89 d1 77 - 00 00 00 00 d0 1f 40 00  .......w......@.
000000000012fe78  48 06 06 00 02 02 00 00 - 00 00 00 00 12 00 a3 00  H...............*----> 符号表 <----*
D:\LsPrj\subjectResearch\DebugAcrossMap\WinMine4Edu\Unicode Release\WinMine.exe

在转储信息中,可以看到报错的地址.

错误 ->00401761 f77d0c           idiv  dword ptr [ebp+0xc] ss:0023:0012fd60=00000000

将编译这个程序时产生的.map文件,.cod文件,转储信息文件放在一起,都打开,分析代码错误行.

map文件中看到程序的基址 = 0x400000

Preferred load address is 00400000

报错地址0x401761附近的函数名称如下:

Address         Publics by Value              Rva+Base       Lib:Object
 0001:000004c0       _GameWon                   004014c0 f   MineGame.obj0001:00000570       _GameLost                  00401570 f   MineGame.obj0001:00000650       _CountMines                00401650 f   MineGame.obj0001:000006f0       _StepBox                   004016f0 f   MineGame.obj0001:00000830       _FillRectStockBrush        00401830 f   MinePaint.obj0001:00000870       _DrawMargin                00401870 f   MinePaint.obj0001:000008b0       _DrawBorder                004018b0 f   MinePaint.obj

计算包含0x401761地址的函数

_StepBox 0x400000 + 0x1000 + 0x6f0 = 0x4016f0

0x401761 报错的代码行

_FillRectStockBrush 0x400000 + 0x1000 + 0x830 = 0x401830

可以看到 0x401761地址在函数_StepBox和_FillRectStockBrush之间, 说明代码中出错的位置在_StepBox函数中~

从转储信息中计算出错位置离函数入口的偏移:

*** ERROR: Module load completed but symbols could not be loaded for D:\LsPrj\subjectResearch\DebugAcrossMap\WinMine4Edu\Unicode Release\WinMine.exe
函数: WinMine00401749 7423             jz      WinMine+0x176e (0040176e)0040174b 6a03             push    0x30040174d 8b450c           mov     eax,[ebp+0xc]00401750 50               push    eax00401751 8b4d08           mov     ecx,[ebp+0x8]00401754 51               push    ecx00401755 e8b6060000       call    WinMine+0x1e10 (00401e10)0040175a 83c40c           add     esp,0xc0040175d 8b4508           mov     eax,[ebp+0x8]00401760 99               cdq
错误 ->00401761 f77d0c           idiv  dword ptr [ebp+0xc] ss:0023:0012fd60=0000000000401764 894508           mov     [ebp+0x8],eax

出错位置离函数入口的偏移(报错地址-_StepBox入口地址) = 0x00401761 - 0x4016f0 = 0x71

从包含_StepBox函数的MineGame.cod中找到离_StepBox入口偏移为0x71的代码行:

_TranslateMouseMsg ENDP
_TEXT   ENDS
PUBLIC  _GameLost
PUBLIC  _GameWon
PUBLIC  _StepBox
;    COMDAT _StepBox
_TEXT   SEGMENT
_r$78102 = -12                     ; size = 4
_c$78103 = -8                      ; size = 4
_cMinesSurround$ = -4                  ; size = 4
_row$ = 8                      ; size = 4
_col$ = 12                     ; size = 4
_StepBox PROC                       ; COMDAT; 282  : {00000 55       push    ebp00001   8b ec        mov     ebp, esp00003  83 ec 0c     sub     esp, 12            ; 0000000cH; 283  :     UINT cMinesSurround;
; 284  :
; 285  :     if (board.Box[row][col].State != BS_INITIAL &&
; 286  :         board.Box[row][col].State != BS_DICEY)00006   8b 45 08     mov     eax, DWORD PTR _row$[ebp]00009 6b c0 78     imul    eax, 120       ; 00000078H0000c    8b 4d 0c     mov     ecx, DWORD PTR _col$[ebp]0000f 8b 94 88 b8 0000 00      mov     edx, DWORD PTR _board[eax+ecx*4+184]00016    c1 e2 1a     shl     edx, 26            ; 0000001aH00019    c1 fa 1b     sar     edx, 27            ; 0000001bH0001c    74 25        je  SHORT $LN11@StepBox0001e  8b 45 08     mov     eax, DWORD PTR _row$[ebp]00021 6b c0 78     imul    eax, 120       ; 00000078H00024    8b 4d 0c     mov     ecx, DWORD PTR _col$[ebp]00027 8b 94 88 b8 0000 00      mov     edx, DWORD PTR _board[eax+ecx*4+184]0002e    c1 e2 1a     shl     edx, 26            ; 0000001aH00031    c1 fa 1b     sar     edx, 27            ; 0000001bH00034    83 fa 02     cmp     edx, 200037    74 0a        je  SHORT $LN11@StepBox; 287  :     {
; 288  :         // previously stepped, must be safe, and no need to step second time
; 289  :         return TRUE;00039  b8 01 00 00 00   mov     eax, 10003e    e9 f9 00 00 00   jmp     $LN12@StepBox
$LN11@StepBox:; 290  :     }
; 291  :
; 292  :     if (board.Box[row][col].fMine)00043    8b 45 08     mov     eax, DWORD PTR _row$[ebp]00046 6b c0 78     imul    eax, 120       ; 00000078H00049    8b 4d 0c     mov     ecx, DWORD PTR _col$[ebp]0004c 8b 94 88 b8 0000 00      mov     edx, DWORD PTR _board[eax+ecx*4+184]00053    c1 e2 1f     shl     edx, 31            ; 0000001fH00056    c1 fa 1f     sar     edx, 31            ; 0000001fH00059    74 23        je  SHORT $LN10@StepBox; 293  :     {
; 294  :         // stepped on a mine!
; 295  :         SetAndDispBoxState(row, col, BS_BLAST);0005b   6a 03        push    30005d 8b 45 0c     mov     eax, DWORD PTR _col$[ebp]00060 50       push    eax00061   8b 4d 08     mov     ecx, DWORD PTR _row$[ebp]00064 51       push    ecx00065   e8 00 00 00 00   call    _SetAndDispBoxState0006a   83 c4 0c     add     esp, 12            ; 0000000cH; 296  :
; 297  :        /** 制造一个BUG, 踩了雷程序就报错, 数组越界
; 298  :        * 程序编译选项不选优化, 否则这里制造的BUG就被干掉了
; 299  :        */
; 300  :        row = row / col;/**< 零列出现雷的时候报除零错 */0006d   8b 45 08     mov     eax, DWORD PTR _row$[ebp]00070 99       cdq00071   f7 7d 0c     idiv    DWORD PTR _col$[ebp]00074  89 45 08     mov     DWORD PTR _row$[ebp], eax; 301  :
; 302  :         return FALSE;00077 33 c0        xor     eax, eax00079  e9 be 00 00 00   jmp     $LN12@StepBox
$LN10@StepBox:; 303  :     }
; 304  :

离入口偏移为0x71的行找到了,果真是一句除零~.

  00071  f7 7d 0c     idiv    DWORD PTR _col$[ebp]

这句汇编对应的代码上就在他的上面:  row = row / col;/**< 零列出现雷的时候报除零错 */

; 300  :         row = row / col;/**< 零列出现雷的时候报除零错 */0006d   8b 45 08     mov     eax, DWORD PTR _row$[ebp]00070 99       cdq00071   f7 7d 0c     idiv    DWORD PTR _col$[ebp]00074  89 45 08     mov     DWORD PTR _row$[ebp], eax

好, 已经找到报错的代码行了。

如果是在开发机上, 就直接可以在Release版不优化带调试符号的工程上单步了.

如果没有条件单步,在报错的代码上上,用调试日志记录关心的上下文,问题就能解决了。

这个扫雷游戏做的太坚固了,还没想到弄个别的非除零错之外的不明显的BUG来找找看.

以后在实际工程中再验证,那时就不会让drwtsn32这么容易的判断是什么具体错误~.

如果有崩溃对话框弹出, 连华生医生也不用了,那时也有转储信息. 可以用来了解客户那的操作系统信息, 当时运行的程序(有没有杀毒软件之类的程序).

experiment:Finding crash information using the MAP file on vs2005相关推荐

  1. iOS调优 | 深入理解Link Map File

    Link Map File初识 我们编写的源码需要经过编译.链接,最终生成一个可执行文件.在编译阶段,每个类会生成对应的.o文件(目标文件).在链接阶段,会把.o文件和动态库链接在一起.Link Ma ...

  2. ArcIMS9.2新增地图服务时check your map file's layers and data source connections解决

    ArcIMS9.2安装完毕后的配置可以参考网上的教程,很详细.其中配置Service时可能会出现以下报错: Error when trying to administer Service: check ...

  3. Echart报错: Map china not exists. You can download map file on.....的解决办法

    Echart报错: Map china not exists. You can download map file on http://echarts.baidu.com/download-map.h ...

  4. 文件格式大全(A-H)

    <前言> 经常有网友问什么什么扩展名的文件要用什么程序来打开,事实上,电脑上 面真正能表示文件的类型并且得到一致承认的扩展名并不是很多,而大多数扩展 名一般都是由使用该文件的软件的开发者定 ...

  5. auto make System.map to C header file

    #!/bin/bash# auto make System.map to C header file # 说明: # 该脚本主要是将Linux内核生成的System.map文件中的符号.地址存入结构体 ...

  6. Crash Dump Analysis 崩溃转储分析-摘抄翻译自深入解析windows操作系统

    Almost every Windows user has heard of, if not experienced, the infamous "blue screen of death. ...

  7. jQuery的jquery-1.10.2.min.map触发404(未找到)

    本文翻译自:jQuery's jquery-1.10.2.min.map is triggering a 404 (Not Found) I'm seeing error messages about ...

  8. 问题-[Delphi]通过Map文件查找内存地址出错代码所在行

     一 什么是MAP文件       什么是 MAP 文件?简单地讲, MAP 文件是程序的全局符号.源文件和代码行号信息的唯一的文本表示方法,它可以在任何地方.任何时候使用,不需要有额外的程序进行支持 ...

  9. ARM 之十 ARMCC(Keil) map 文件(映射文件)详解

    在看这篇文章之前 需要对 ARM ELF 文件有一定的了解.了解什么是域(Region).节(Section,也称为节区).段(Segment).镜像(Image).镜像文件(Image File)等 ...

最新文章

  1. 使用css实现瀑布流的效果
  2. 使用sourceInsight 提高代码编写效率
  3. php sku添加,php – 在单个产品页面中显示SKU下的自定义字段值
  4. php 返回查询结果某个字段
  5. java修改文件的大小限制_Struts2修改上传文件大小限制方法解析
  6. Windows 技术篇-WPS关闭推送广告配置方法
  7. Spring Boot-场景启动器
  8. 更新系统时跳过某个软件包
  9. 你可能不知道的Docker资源限制
  10. mysql用in查询list_Mysql优化器对in list的处理
  11. macos实现输入文件输入结束符
  12. Eucalyptus-NC管理
  13. Win7安装RNDIS驱动
  14. 免费高清图片素材网站
  15. 抖音上热门精选技巧 小视频更改md5
  16. 通过aosp-latest下载Android源码
  17. Codeforces Round #521 (Div. 3) E - Thematic Contests (二分 + STL)
  18. 安霸Ambarella三款CV系列芯片对比--CV2S、CV22S、CV25S
  19. 制作NGUI动态字体
  20. docker 搭建frp内网穿透以及frp详细使用

热门文章

  1. 去掉iPhone safari下手机号码默认的下划线
  2. 完美解决 Git-Failed to connect to github.com port 443问题
  3. linux环境下启动数据库
  4. 基于小世界网络/无标度网络/复杂网络进行SEIR病毒传播仿真研究
  5. Unity3D 设计模式学习之观察者模式
  6. forest -http工具
  7. Tomcat 闪退解决方法
  8. 面试题精选:数据伪造
  9. 如何隐藏或删除Windows 10任务栏图标
  10. 并查集小结 (参考birdfly+修改)