分析包含 MSVCR 异常的转储文件

Analyze a dump file that contains a MSVCR exception

我有以下带有 msvcr100!_CxxThrowException 的线程堆栈。

 # ChildEBP RetAddr  Args to Child              
00 0973ef38 7739bf53 7739610a 00000000 00000000 ntdll!KiFastSystemCallRet
01 0973ef70 7738965e 0019029e 00000000 00000001 user32!NtUserWaitMessage+0xc
02 0973ef98 7739f762 77380000 0016aa20 00000000 user32!InternalDialogBox+0xd0
03 0973f258 7739f047 0973f3b4 00000000 ffffffff user32!SoftModalMessageBox+0x94b
04 0973f3a8 7739eec9 0973f3b4 00000028 00000000 user32!MessageBoxWorker+0x2ba
05 0973f400 773d7d0d 00000000 001aaf18 0019bb60 user32!MessageBoxTimeoutW+0x7a
06 0973f434 773c42c8 00000000 7787b9f0 7786c24c user32!MessageBoxTimeoutA+0x9c
07 0973f454 773c42a4 00000000 7787b9f0 7786c24c user32!MessageBoxExA+0x1b
08 0973f470 7786f265 00000000 7787b9f0 7786c24c user32!MessageBoxA+0x45
09 0973f4a4 7786c20f 7787b9f0 7786c24c 00012010 netman!__crtMessageBoxA+0xf6
0a 0973f4cc 7786f34e 0000000a 00000000 0973f788 netman!_NMSG_WRITE+0x127
0b 0973f4fc 7786d6b6 77ecb7c0 0973f760 77e761b7 netman!abort+0x7
0c 0973f508 77e761b7 0973f788 00000000 00000000 netman!__CxxUnhandledExceptionFilter+0x2f
0d 0973f760 77e792a3 0973f788 77e61ac1 0973f790 kernel32!UnhandledExceptionFilter+0x12a
0e 0973f768 77e61ac1 0973f790 00000000 0973f790 kernel32!BaseThreadStart+0x4a
0f 0973f790 7c828772 0973fb4c 0973ffdc 0973f86c kernel32!_except_handler3+0x61
10 0973f7b4 7c828743 0973fb4c 0973ffdc 0973f86c ntdll!ExecuteHandler2+0x26
11 0973f85c 7c82865c 09737000 0973f86c 00010007 ntdll!ExecuteHandler+0x24
12 0973fb3c 77e4bef7 0973fb4c 0000000f e06d7363 ntdll!RtlRaiseException+0x3d
13 0973fb9c 78ac872d e06d7363 00000001 00000003 kernel32!RaiseException+0x53
14 0973fbd4 0084bb9e 0973fc38 00bd8470 9adbd99a msvcr100!_CxxThrowException+0x48

当我查看 msvcr100!_CxxThrowException 框架时,我看到以下信息。我如何逐步分析此转储以确定 MSVCR 异常的原因?

14 0973fbd4 0084bb9e msvcr100!_CxxThrowException+0x48 [f:\dd\vctools\crt_bld\self_x86\crt\prebuild\eh\throw.cpp @ 157]
0973fbdc          void * pExceptionObject = 0x0973fc38
0973fbe0          struct _s__ThrowInfo * pThrowInfo = 0x00bd8470
0973fbb4          struct EHExceptionRecord ThisException = struct EHExceptionRecord
78ac8734          struct EHExceptionRecord ExceptionTemplate = struct EHExceptionRecord

编辑: 在我写这个答案的时候,我并不知道下面其他张贴者建议的更好、更简单的方法。所以请向下滚动并查看他们的答案!


根据您的评论,您无法真正深入分析堆栈跟踪。

要至少获取有关异常本身的详细信息(仅当它是您有符号的异常时,例如 std 中的符号),您可以执行以下操作:

我准备了一个简单的测试文件:

#include <stdexcept>

int main()
{
    throw std::runtime_error("Oh noez!");
}

然后我 运行 在 WinDbg 中:

CommandLine: Z:\Temp\testexception\bin\Debug\testexception.exe

************* Symbol Path validation summary **************
Response                         Time (ms)     Location
Deferred                                       symsrv*symsrv.dll*c:\users\david\symbols*http://msdl.microsoft.com/download/symbols
Symbol search path is: symsrv*symsrv.dll*c:\users\david\symbols*http://msdl.microsoft.com/download/symbols
Executable search path is: 
ModLoad: 00910000 00919000   testexception.exe
ModLoad: 771a0000 7731b000   ntdll.dll
ModLoad: 75b60000 75c40000   C:\WINDOWS\SysWOW64\KERNEL32.DLL
ModLoad: 73ef0000 7406e000   C:\WINDOWS\SysWOW64\KERNELBASE.dll
ModLoad: 0fb60000 0fcd3000   C:\WINDOWS\SysWOW64\MSVCR100D.dll
(4de4.178c): Break instruction exception - code 80000003 (first chance)
eax=00000000 ebx=00000003 ecx=039b0000 edx=00000000 esi=009100e8 edi=00360000
eip=7724ccbc esp=0018f524 ebp=0018f550 iopl=0         nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
ntdll!LdrpDoDebuggerBreak+0x2b:
7724ccbc cc              int     3
Processing initial command '.prefer_dml 1'
0:000> .prefer_dml 1
DML versions of commands on by default
0:000> bp ntdll!ExecuteHandler2 <<<<<< This is just to get a stack more similar to yours
0:000> g
(4de4.178c): C++ EH exception - code e06d7363 (first chance)
Breakpoint 0 hit
eax=00000000 ebx=00000000 ecx=64905de5 edx=7722b670 esi=00000000 edi=00000000
eip=7722b62c esp=0018f3cc ebp=0018f490 iopl=0         nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
ntdll!ExecuteHandler2:
7722b62c 55              push    ebp
0:000> kb
 # ChildEBP RetAddr  Args to Child              
00 0018f3c8 7722b624 0018f4a8 0018fa4c 0018f4f8 ntdll!ExecuteHandler2
01 0018f490 77218e7f 0018f4a8 0018f4f8 0018f4a8 ntdll!ExecuteHandler+0x24
02 0018f490 73fadad8 0018f4a8 0018f4f8 0018f4a8 ntdll!KiUserExceptionDispatcher+0xf
03<0018f9b0>0fc5cf82 e06d7363 00000001 00000003 KERNELBASE!RaiseException+0x48
*** WARNING: Unable to verify checksum for testexception.exe
04 0018f9f0 00911071 0018fa00 009153a8 00914790 MSVCR100D!_CxxThrowException+0x52
05 0018fa0c 009114df 00000001 00a14f78 00a12358 testexception!main+0x21
06 0018fa5c 0091130f 0018fa78 75b738f4 00360000 testexception!__tmainCRTStartup+0x1bf
07 0018fa64 75b738f4 00360000 75b738d0 380b229d testexception!mainCRTStartup+0xf
08 0018fa78 77205de3 00360000 6488a725 00000000 KERNEL32!BaseThreadInitThunk+0x24
09 0018fac0 77205dae ffffffff 7722b7d2 00000000 ntdll!__RtlUserThreadStart+0x2f
0a 0018fad0 00000000 00911300 00360000 00000000 ntdll!_RtlUserThreadStart+0x1b
0:000> dds 0018f9b0 l6 <<<<<< The address is from the line with RaiseException above, I marked it with < >
0018f9b0  0018f9f0
0018f9b4  0fc5cf82 MSVCR100D!_CxxThrowException+0x52
0018f9b8  e06d7363
0018f9bc  00000001
0018f9c0  00000003
0018f9c4  0018f9e4 <<<<<< This is the address of the arguments array
0:000> dpp 0018f9e4 l3
0018f9e4  19930520
0018f9e8 <0018fa00>00914790 <testexception!std::runtime_error>::`vftable' <<<<<< this is the exception
0018f9ec  009153a8 00000000
0:000> dt 0018fa00 testexception!std::runtime_error <<<<<< remove the `vftable` part (again marked with < > above)
   +0x000 __VFN_table : 0x00914790 
   +0x004 _Mywhat          : 0x00a11068  "Oh noez!" <<<<<< Here is our message from the code
   +0x008 _Mydofree        : 1

@CherryDT 的回答应该没问题。我只想分享另一种方法。

  1. .symfix
  2. .sympath+ <your private symbols>
  3. .reload
  4. .exr -1
  5. dp <parameter 1> L1
  6. ln <result of dp>
  7. dt <type of ln> <parameter 1>

它应该看起来像这样(跳过符号部分):

0:000> .exr -1
ExceptionAddress: 7689c41f (KERNELBASE!RaiseException+0x00000058)
   ExceptionCode: e06d7363 (C++ EH exception)
  ExceptionFlags: 00000001
NumberParameters: 3
   Parameter[0]: 19930520
   Parameter[1]: 004bfb68
   Parameter[2]: 003370b8

0:000> dp 004bfb68 L1
004bfb68  0f5cf1d0

0:000> ln 0f5cf1d0
(0f5cf1d0)   MSVCR110D!std::exception::`vftable'   |  (0f5cf1d8)   MSVCR110D!`string'
Exact matches:
    MSVCR110D!std::exception::`vftable' = <no type information>

0:000> dt std::exception 004bfb68
SimpleCppCrash!std::exception
   +0x000 __VFN_table : 0x0f5cf1d0 
   +0x004 _Mywhat          : 0x0059f410  "Ouch: This application crashed because ..."
   +0x008 _Mydofree        : 1

如果您在使用 MSVCRxxD 的符号时遇到问题,我发现 !analyze -v 会有所帮助(我没有找到解决问题的实际方法)。

替代方法

$exr_param0,14 are PseudoRegisters for _EXCEPTION_RECORD->异常信息[15]

ExceptionInformation[2] 是 pExceptionObject

0:000> da poi($exr_param1+4)
0046ad00  "Oh noez!"

如果您使用最新的 windbg drop,您可以使用 Natvis Expression Evaluator 像这样查看

0:000> dx Debugger.State.DebuggerVariables.curprocess.Threads.First().Stack.Frames[1].LocalVariables.ThisException.params
Debugger.State.DebuggerVariables.curprocess.Threads.First().Stack.Frames[1].LocalVariables.ThisException.params                 [Type: EHExceptionRecord::EHParameters]
    [+0x000] magicNumber      : 0x19930520
    [+0x004] pExceptionObject : 0x30f9a4 [Type: void *]
    [+0x008] pThrowInfo       : 0x133728 [Type: _s_ThrowInfo *]

0:000> ?? ((stdexcept!std::runtime_error *) @$exr_param1 )->_Data
struct __std_exception_data
   +0x000 _What            : 0x003dad00  "Oh noez!"
   +0x004 _DoFree          : 1