(转)利用WinDbg找出程序崩溃的代码行号
在程序运行过程中,遇到错误时不时崩溃,说程序不时的崩溃,什么xxoo不能read的!
如果光要是这个内存地址,估计你会疯掉~~
所以分享一下基本的调试技巧,需要准备的工具有WinDbg + VC6.0,
下面是自己整理的一份自动生成DUMP文件的源代码,只需要添加到工程即可,源代码如下:
MiniDump.h
MiniDump.cpp
原文链接地址: http://blog.csdn.net/wangningyu/article/details/6748138
原作者上传的测试代码:http://download.csdn.net/download/wangningyu/3575167
http://www.cctry.com/thread-41078-1-1.html
pdb文件的说明和微软符号下载:http://blog.csdn.net/xl_lbj/article/details/11604035
http://blog.csdn.net/bytxl/article/details/46722881
VC++6.0编译release版本程序生成pdb调试信息:http://blog.csdn.net/beanjoy/article/details/7294679
用VC6.0建立一个基于对话框程序
1、在CXXDlg::OnInitDialog()中添加这样一段:
BOOL CTestDlg::OnInitDialog() { CDialog::OnInitDialog(); // ...... SetUnhandledExceptionFilter(CrashReportEx); HMODULE hKernel32; // Try to get MiniDumpWriteDump() address. hDbgHelp = LoadLibrary("DBGHELP.DLL"); MiniDumpWriteDump_ = (MINIDUMP_WRITE_DUMP)GetProcAddress(hDbgHelp, "MiniDumpWriteDump"); // d("hDbgHelp=%X, MiniDumpWriteDump_=%X", hDbgHelp, MiniDumpWriteDump_); // Try to get Tool Help library functions. hKernel32 = GetModuleHandle("KERNEL32"); CreateToolhelp32Snapshot_ = (CREATE_TOOL_HELP32_SNAPSHOT)GetProcAddress(hKernel32, "CreateToolhelp32Snapshot"); Module32First_ = (MODULE32_FIRST)GetProcAddress(hKernel32, "Module32First"); Module32Next_ = (MODULE32_NEST)GetProcAddress(hKernel32, "Module32Next"); }
下面是工程中的测试代码:
class CTestDlg : public CDialog { // Construction public: CTestDlg(CWnd* pParent = NULL); // standard constructor void Fun1(char *pszBuffer); void Fun2(char *pszBuffer); void Fun3(char *pszBuffer); };
void CTestDlg::Fun1(char *pszBuffer) { Fun2(pszBuffer); } void CTestDlg::Fun2(char *pszBuffer) { Fun3(pszBuffer); } void CTestDlg::Fun3(char *pszBuffer) { pszBuffer[1] = 0x00; }
我们在双击确定按钮时的响应代码如下:
void CTestDlg::OnOK() { // TODO: Add extra validation here Fun1(NULL); }

其中Generate mapfile可以勾选,也可以不勾选

3、将编译生成的Release目录中的pdb、map文件(如果上面的步骤没有勾选,就不生成map文件)保存起来,以后调试会用到:
,这里就没有勾选生成map文件,有生成pdb文件。(release版也是这样的,在对应文件夹下)
4、运行程序,单击确定按钮出现异常后自动重启,并创建一个Log文件夹,里面生成dump文件:

5、我们打开WinDbg,设置一下相关路径
A、设置pdb路径(File \ Symbol File Path)

B、设置源代码路径( File \ Source File Path )

C、设置Exe路径( File \ Image File Path )

6、用WinDbg打开dump文件(File \ Open Crash Dump)

7、输入命令!analyze -v,等待几秒后会打印出错误信息,函数调用栈如下图:
0:000> !analyze -v ******************************************************************************* * * * Exception Analysis * * * ******************************************************************************* *** ERROR: Symbol file could not be found. Defaulted to export symbols for MFC42D.DLL - GetPageUrlData failed, server returned HTTP status 404 URL requested: http://watson.microsoft.com/StageOne/Test_exe/1_0_0_1/58c6045e/Test_exe/1_0_0_1/58c6045e/c0000005/00002d60.htm?Retriage=1 FAULTING_IP: Test!CTestDlg::Fun3+20 [E:\vcDemo\Test\TestDlg.cpp @ 141] 00402d60 c6400100 mov byte ptr [eax+1],0 EXCEPTION_RECORD: ffffffff -- (.exr 0xffffffffffffffff) ExceptionAddress: 00402d60 (Test!CTestDlg::Fun3+0x00000020) ExceptionCode: c0000005 (Access violation) ExceptionFlags: 00000000 NumberParameters: 2 Parameter[0]: 00000001 Parameter[1]: 00000001 Attempt to write to address 00000001 PROCESS_NAME: Test.exe ERROR_CODE: (NTSTATUS) 0xc0000005 - 0x%08lx EXCEPTION_CODE: (NTSTATUS) 0xc0000005 - 0x%08lx EXCEPTION_PARAMETER1: 00000001 EXCEPTION_PARAMETER2: 00000001 WRITE_ADDRESS: 00000001 FOLLOWUP_IP: Test!CTestDlg::Fun3+20 [E:\vcDemo\Test\TestDlg.cpp @ 141] 00402d60 c6400100 mov byte ptr [eax+1],0 MOD_LIST: <ANALYSIS/> FAULTING_THREAD: 00008884 BUGCHECK_STR: APPLICATION_FAULT_NULL_CLASS_PTR_DEREFERENCE_INVALID_POINTER_WRITE PRIMARY_PROBLEM_CLASS: NULL_CLASS_PTR_DEREFERENCE DEFAULT_BUCKET_ID: NULL_CLASS_PTR_DEREFERENCE LAST_CONTROL_TRANSFER: from 00402d19 to 00402d60 STACK_TEXT: 0012f530 00402d19 00000000 0012f5e8 001986e0 Test!CTestDlg::Fun3+0x20 [E:\vcDemo\Test\TestDlg.cpp @ 141] 0012f58c 00402cc9 00000000 0012f644 001986e0 Test!CTestDlg::Fun2+0x29 [E:\vcDemo\Test\TestDlg.cpp @ 137] 0012f5e8 00403267 00000000 0012f8e4 001986e0 Test!CTestDlg::Fun1+0x29 [E:\vcDemo\Test\TestDlg.cpp @ 132] 0012f644 5f4398cc 0012f8e4 001986e0 00000000 Test!CTestDlg::OnOK+0x27 [E:\vcDemo\Test\TestDlg.cpp @ 242] WARNING: Stack unwind information not available. Following frames may be wrong. 0012f67c 5f439ffb 0012fe3c 00000001 00000000 MFC42D!Ordinal563+0x133 0012f6d4 5f435c1b 00000001 00000000 00000000 MFC42D!Ordinal3657+0x274 0012f704 5f431f33 00000001 00000000 00000000 MFC42D!Ordinal3658+0x24 0012f764 5f431135 00000001 006005fc 0012f8e4 MFC42D!Ordinal3670+0x138 0012f864 5f4310b8 00000111 00000001 006005fc MFC42D!Ordinal4118+0x53 0012f884 5f42ec09 00000111 00000001 006005fc MFC42D!Ordinal5076+0x2e 0012f8f8 5f42f0f5 0012fe3c 005a0588 00000111 MFC42D!Ordinal1045+0xed 0012f924 5f49265d 005a0588 00000111 00000001 MFC42D!Ordinal1192+0xad 0012f954 7600c4b7 005a0588 00000111 00000001 MFC42D!Ordinal1193+0x4a 0012f980 7600c5b7 5f492613 005a0588 00000111 user32!InternalCallWinProc+0x23 0012f9f8 7600526c 00000000 5f492613 005a0588 user32!UserCallWinProcCheckWow+0x14b 0012fa38 7600555a 007c9b40 007ca9e0 00000001 user32!SendMessageWorker+0x4d0 0012fa58 760396b5 005a0588 00000111 00000001 user32!SendMessageW+0x7c 0012fa70 760397b5 007c9e28 00000000 007c9e28 user32!xxxButtonNotifyParent+0x41 0012fa8c 76027ed1 0019e124 00000001 00000000 user32!xxxBNReleaseCapture+0xf7 0012fb10 76018285 007c9e28 00000202 00000000 user32!ButtonWndProcWorker+0x911 0012fb30 7600c4b7 006005fc 00000202 00000000 user32!ButtonWndProcA+0x4c 0012fb5c 7600c5b7 7601db9d 006005fc 00000202 user32!InternalCallWinProc+0x23 0012fbd4 7600cbe9 00000000 7601db9d 006005fc user32!UserCallWinProcCheckWow+0x14b 0012fc34 7600cc40 7601db9d 00000000 0012fc68 user32!DispatchMessageWorker+0x357 0012fc44 760041c3 004177e0 004177e0 004177e8 user32!DispatchMessageW+0xf 0012fc68 76012043 005a0588 007c9e28 0012fea4 user32!IsDialogMessageW+0x588 0012fc88 5f438bf5 005a0588 004177e0 0012fea4 user32!IsDialogMessageA+0x10c 0012fcac 5f434464 004177e0 0012fea4 00000000 MFC42D!Ordinal3337+0x7b 0012fcc8 5f435bee 004177e0 0012fea4 00000000 MFC42D!Ordinal4206+0x75 0012fcec 5f433018 004177e0 0012fea4 00000000 MFC42D!Ordinal4208+0xf8 0012fd0c 5f43b776 005a0588 004177e0 004177a8 MFC42D!Ordinal5070+0x98 0012fd28 5f43bbdd 004177e0 0012fea4 00000000 MFC42D!Ordinal4215+0x55 0012fd44 5f43466f 0012fea4 00000000 7ffd9000 MFC42D!Ordinal4239+0xe2 0012fd80 5f436a6f 00000004 0012fea4 00000000 MFC42D!Ordinal4410+0x202 0012fde0 004025ec 00000000 00000000 7ffd9000 MFC42D!Ordinal1862+0x191 0012feb0 5f4359f3 00000000 00000000 7ffd9000 Test!CTestApp::InitInstance+0x6c [E:\vcDemo\Test\Test.cpp @ 59] 0012fed0 004038e8 00400000 00000000 00172d0d MFC42D!Ordinal1190+0x83 0012fee8 00403763 00400000 00000000 00172d0d Test!WinMain+0x18 [appmodul.cpp @ 30] 0012ff88 7622ef1c 7ffd9000 0012ffd4 77d83648 Test!WinMainCRTStartup+0x1b3 [crtexe.c @ 330] 0012ff94 77d83648 7ffd9000 77ae81ff 00000000 kernel32!BaseThreadInitThunk+0xe 0012ffd4 77d8361b 004035b0 7ffd9000 00000000 ntdll!__RtlUserThreadStart+0x70 0012ffec 00000000 004035b0 7ffd9000 00000000 ntdll!_RtlUserThreadStart+0x1b STACK_COMMAND: ~0s; .ecxr ; kb FAULTING_SOURCE_CODE: 137: } 138: 139: void CTestDlg::Fun3(char *pszBuffer) 140: { > 141: pszBuffer[1] = 0x00; 142: } 143: 144: BOOL CTestDlg::OnInitDialog() 145: { 146: CDialog::OnInitDialog(); SYMBOL_STACK_INDEX: 0 SYMBOL_NAME: test!CTestDlg::Fun3+20 FOLLOWUP_NAME: MachineOwner MODULE_NAME: Test IMAGE_NAME: Test.exe DEBUG_FLR_IMAGE_TIMESTAMP: 58c6045e FAILURE_BUCKET_ID: NULL_CLASS_PTR_DEREFERENCE_c0000005_Test.exe!CTestDlg::Fun3 BUCKET_ID: APPLICATION_FAULT_NULL_CLASS_PTR_DEREFERENCE_INVALID_POINTER_WRITE_test!CTestDlg::Fun3+20 WATSON_STAGEONE_URL: http://watson.microsoft.com/StageOne/Test_exe/1_0_0_1/58c6045e/Test_exe/1_0_0_1/58c6045e/c0000005/00002d60.htm?Retriage=1 Followup: MachineOwner ---------
这样我们就能在发布版本的程序中,准确的定位到哪个函数出了问题,所以发布程序时,一定要记得生成pdb文件,不然客户运行出错的话,你不死也残!
使用windbg调试时,需要注意的是pdb的版本与产生dump的exe或dll版本必须一致(保证是同一时间编译后生成的)。
有时候只加载自己的pdb还看不出问题所在,需要加载微软的pdb:
在symbols输入框里,除了自己pdb的路径外,还应输入“srv*sym*http://msdl.microsoft.com/download/symbols”,自动加载系统模块所需的dll。
输入pdb路径后,最好再用命令reload -f强制加载pdb。
另外,一般不通过命令行来分析,因为windbg有各种窗口。我一般打开进程窗口、堆栈窗口和源代码窗口进行分析。
浙公网安备 33010602011771号