WinDbg 查找问题异常堆栈,堆栈跟踪UnhandledExceptionFilter

  1. UnhandledExceptionFilter 函数调用时没有异常处理程序定义来处理引发的异常。 函数通常将异常传递达 Ntdll.dll 文件这将捕捉并试图处理它。 

    在该进程的内存快照存在某些情况下,您可以看到到一个线程持有锁点的线程调用的 UnhandledExceptionFilter 函数。 在这些情况中您可以按照本文标识导致异常的 DLL 中的步骤。

Windbg.exe 打开转储文件

  1. 下载并安装调试程序。 要下载调试程序,请访问下面的 Microsoft 网站:
  2. 转到windbg目录,采用工具cdb生成dump文件:cdb -pv -pn 进程名 -c ".dump /m c:/文件名.dmp;q",例如: cdb -pv -pn explorer.exe -c ".dump /m c:/explorer.dmp;q"
  3. 打开该调试器的安装位置文件夹,然后双击 Windbg.exe 以启动调试器。
  4. 在 文件 菜单上单击 打开故障转储 (或按 CTRL + D),然后选择您要查看该转储文件。
' 异常堆栈使用 Windbg.exe
  1. 在 Windbg.exe,打开.dmp 文件,该进程。
  2. 请确保以正确的位置指向符号路径。 有关如何执行此操作的详细信息请访问下面的 Microsoft 网站:
    如何获取符号
    http://www.microsoft.com/whdc/devtools/ddk/default.mspx  (http://www.microsoft.com/whdc/devtools/ddk/default.mspx)
  3. 在命令提示符处键入 ~*kb 要列出所有进程中线程。
  4. 标识进行函数调用的线程 Kernel32! UnhandledExceptionFilter。 它看起来类似于以下内容:
    120  id: f0f0f0f0.a1c   Suspend: 1 Teb 7ff72000 Unfrozen
    ChildEBP RetAddr Args to Child
    09a8f334 77eb9b46 0000244c 00000001 00000000 ntdll!ZwWaitForSingleObject+0xb [i386/usrstubs.asm @ 2004]
    09a8f644 77ea7e7a 09a8f66c 77e861ae 09a8f674 KERNEL32!UnhandledExceptionFilter+0x2b5
    [D:/nt/private/windows/base/client/thread.c @ 1753]
    09a8ffec 00000000 787bf0b8 0216fe94 00000000 KERNEL32!BaseThreadStart+0x65 [D:/nt/private/windows/base/client/support.c @ 453]
  5. 切换到该线程 (在此示例中,线程是"~ 120s")。
  6. 显示内存内容的第一个参数指定位置处 Kernel32! UnhandledExceptionFilter 通过使用 dd 第一个参数。 这指向 EXCEPTION_POINTERS 结构
    0:120> dd 09a8f66c 
    09a8f66c 09a8f738 09a8f754 09a8f698 77f8f45c
    09a8f67c 09a8f738 09a8ffdc 09a8f754 09a8f710
    09a8f68c 09a8ffdc 77f8f5b5 09a8ffdc 09a8f720
    09a8f69c 77f8f3fa 09a8f738 09a8ffdc 09a8f754
    09a8f6ac 09a8f710 77e8615b 09a8fad4 00000000
    09a8f6bc 09a8f738 74a25336 09a8f6e0 09a8f910
    09a8f6cc 01dc8ad8 0d788918 00000001 018d1f28
    09a8f6dc 00000001 61746164 7073612e 09a8f71c
  7. 第一个 dword 值表示异常记录。 若要获取有关异常的类型的信息,请在命令提示符处运行以下:
    .exr first DWORD from step 6
    0:120> .exr 09a8f738 
    ExceptionAddress: 78011f32 (MSVCRT!strnicmp+0x00000092)
    ExceptionCode: c0000005
    ExceptionFlags: 00000000
    NumberParameters: 2
    Parameter[0]: 00000000
    Parameter[1]: 00000000
    Attempt to read from address 00000000
  8. 第二个 dword 值是上下文记录。 要获取的上下文信息,请在命令提示符处运行以下:
    .cxr second DWORD from step 6
    0:120> .cxr 09a8f754 
    eax=027470ff ebx=7803cb28 ecx=00000000 edx=00000000 esi=00000000 edi=09a8fad4
    eip=78011f32 esp=09a8fa20 ebp=09a8fa2c iopl=0 nv up ei ng nz na po nc
    cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010286
    MSVCRT!strnicmp+92:
    78011f32 8a06 mov al,[esi]
  9. 运行 kv 命令以获得实际的异常的调用堆栈。 这可以帮助您识别可能不具有被正确处理过程中的实际问题
    0:120> kv
    ChildEBP RetAddr Args to Child
    WARNING: Stack unwind information not available. Following frames may be wrong.
    09a8fa2c 780119ab 09a8fad4 00000000 09a8faa8 MSVCRT!strnicmp+0x92
    09a8fa40 7801197c 09a8fad4 00000000 6d7044fd MSVCRT!stricmp+0x3c
    09a8fa80 6e5a6ef6 09a8fad4 2193d68d 00e5e298 MSVCRT!stricmp+0xd
    09a8fa94 6d7043bf 09a8fad4 09a8faa8 0000001c IisRTL!CLKRHashTable::FindKey+0x59 (FPO: [2,0,1])
    09a8faac 749fc22d 09a8fad4 01d553b0 0000001c ISATQ!CDirMonitor::FindEntry+0x1e
    (FPO: [Non-Fpo]) [D:/nt/private/inet/iis/svcs/infocomm/atq/dirmon.cpp @ 884]
    09a8fac4 749fd1cb 09a8fad4 09a8fb10 525c3a46 asp!RegisterASPDirMonitorEntry+0x6e
    (FPO: [EBP 0x09a8fb08] [2,0,4]) [D:/nt/private/inet/iis/svcs/cmp/asp/aspdmon.cpp @ 534]
    09a8fb08 749fcdd6 00000000 09a8fcbc 018d1f28 asp!CTemplateCacheManager::RegisterTemplateForChangeNotification+0x8a
    (FPO: [Non-Fpo]) [D:/nt/private/inet/iis/svcs/cmp/asp/cachemgr.cpp @ 621]
    09a8fb3c 74a08bfe 00000000 000000fa 74a30958 asp!CTemplateCacheManager::Load+0x382
    (FPO: [Non-Fpo]) [D:/nt/private/inet/iis/svcs/cmp/asp/cachemgr.cpp @ 364]
    09a8fc68 74a0d4c9 04c12518 018d1f28 09a8fcbc asp!LoadTemplate+0x42
    (FPO: [Non-Fpo]) [D:/nt/private/inet/iis/svcs/cmp/asp/exec.cpp @ 1037]
    09a8fcc0 74a2c3e5 00000000 0637ee38 09a8fd58 asp!CHitObj::ViperAsyncCallback+0x3e8
    (FPO: [Non-Fpo]) [D:/nt/private/inet/iis/svcs/cmp/asp/hitobj.cpp @ 2414]
    09a8fcd8 787c048a 00000000 77aa1b03 01e91ed8 asp!CViperAsyncRequest::OnCall+0x3f
    (FPO: [Non-Fpo]) [D:/nt/private/inet/iis/svcs/cmp/asp/viperint.cpp @ 194]
    09a8fce0 77aa1b03 01e91ed8 77a536d8 00000000 COMSVCS!STAActivityWorkHelper+0xa
    (FPO: [1,0,0])
    09a8fd24 77aa1927 000752f8 000864dc 787c0480 ole32!EnterForCallback+0x6a
    (FPO: [Non-Fpo]) [D:/nt/private/ole32/com/dcomrem/crossctx.cxx @ 1759]
    09a8fe50 77aa17ea 000864dc 787c0480 01e91ed8 ole32!SwitchForCallback+0x12b
    (FPO: [Non-Fpo]) [D:/nt/private/ole32/com/dcomrem/crossctx.cxx @ 1644]
    09a8fe78 77aa60c1 000864dc 787c0480 01e91ed8 ole32!PerformCallback+0x50
    (FPO: [Non-Fpo]) [D:/nt/private/ole32/com/dcomrem/crossctx.cxx @ 1559]
    09a8fed4 77aa5fa6 04f2b4c0 787c0480 01e91ed8 ole32!CObjectContext::InternalContextCallback+0xf5
    (FPO: [Non-Fpo]) [D:/nt/private/ole32/com/dcomrem/context.cxx @ 3866]
    09a8fef4 787bd3c3 04f2b4c0 787c0480 01e91ed8 ole32!CObjectContext::DoCallback+0x1a
    (FPO: [Non-Fpo]) [D:/nt/private/ole32/com/dcomrem/context.cxx @ 3746]
    09a8ff24 787bf373 0216fb3c 00000007 09a8ffec COMSVCS!STAActivityWork::DoWork+0x73
    (FPO: [0,4,2])
    09a8ffb4 77e8758a 0216fe94 0216fb3c 00000007 COMSVCS!STAThread::STAThreadWorker+0x2bb
    (FPO: [EBP 0x09a8ffec] [1,31,4])
    09a8ffec 00000000 787bf0b8 0216fe94 00000000 KERNEL32!BaseThreadStart+0x52
    (FPO: [Non-Fpo]) [D:/nt/private/windows/base/client/support.c @ 451]

_except_handler函数的情况

  1. 有些情况下堆栈中没有UnhandledExceptionFilter,而只有_except_handler函数,这个是SEH异常处理函数。函数原型:EXCEPTION_DISPOSITION __cdecl _except_handler( 
                             struct _EXCEPTION_RECORD *ExceptionRecord,
                             void * EstablisherFrame,
                             struct _CONTEXT *ContextRecord,
                             void * DispatcherContext); 
    这个函数的第一个参数是一个指向 EXCEPTION_RECORD 结构的指针。这个结构在WINNT.H中定义,如下所示: 
    typedef struct _EXCEPTION_RECORD {
       DWORD ExceptionCode;
       DWORD ExceptionFlags;
       struct _EXCEPTION_RECORD *ExceptionRecord;
       PVOID ExceptionAddress;
       DWORD NumberParameters;
       DWORD ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
    } EXCEPTION_RECORD; 
    _except_handler 函数的第二个参数是一个指向establisher帧结构的指针。
    _except_handler 回调函数的第三个参数是一个指向 CONTEXT 结构的指针。
    typedef struct _CONTEXT
    {
        DWORD ContextFlags;
        DWORD Dr0;
        DWORD Dr1;
        DWORD Dr2;
        DWORD Dr3;
        DWORD Dr6;
        DWORD Dr7;
        FLOATING_SAVE_AREA FloatSave;
        DWORD SegGs;
        DWORD SegFs;
        DWORD SegEs;
        DWORD SegDs;
        DWORD Edi;
        DWORD Esi;
        DWORD Ebx;
        DWORD Edx;
        DWORD Ecx;
        DWORD Eax;
        DWORD Ebp;
        DWORD Eip;
        DWORD SegCs;
        DWORD EFlags;
        DWORD Esp;
        DWORD SegSs;
    } CONTEXT; 
    _except_handler 回调函数的第四个参数被称为DispatcherContext。
  2. 分析dump文件时,在命令提示符处键入 ~*kb 要列出所有进程中线程。
  3. 标识进行函数调用的线程 Kernel32!_except_handler。 它看起来类似于以下内容:
       9  Id: 918.117c Suspend: 2 Teb: 7ffd8000 Unfrozen
    ChildEBP RetAddr  Args to Child             
    085df400 7c9232a8 085df4ec 085dffdc 085df50c kernel32!_except_handler3+0x61
    085df424 7c92327a 085df4ec 085dffdc 085df50c ntdll!ExecuteHandler2+0x26
    085df4d4 7c92e48a 00000000 085df50c 085df4ec ntdll!ExecuteHandler+0x24
  4. 切换到该线程 (在此示例中,线程是"~ 9s")。
  5. Kernel32! !_except_handler第一个参数 dword 值表示异常记录。 若要获取有关异常的类型的信息,请在命令提示符处运行以下: .exr first DWORD from step 5
    0:009> .exr 085df4ec
    ExceptionAddress: 7c812afb (kernel32!RaiseException+0x00000053)
       ExceptionCode: e06d7363 (C++ EH exception)
      ExceptionFlags: 00000001
    NumberParameters: 3
       Parameter[0]: 19930520
       Parameter[1]: 085df874
       Parameter[2]: 006c010c
  6. Kernel32! !_except_handler第三个参数 dword 值是上下文记录。 要获取的上下文信息,请在命令提示符处运行以下:
    .cxr second DWORD from step 6
    0:009> .cxr 085df50c 
    eax=085df7dc ebx=00005d34 ecx=00000000 edx=01240608 esi=085df864 edi=00100000
    eip=7c812afb esp=085df7d8 ebp=085df82c iopl=0         nv up ei pl nz na pe nc
    cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
    kernel32!RaiseException+0x53:
    7c812afb 5e              pop     esi
  7. 运行 kv 命令以获得实际的异常的调用堆栈。 这可以帮助您识别可能不具有被正确处理过程中的实际问题
    0:009> kv
    ChildEBP RetAddr Args to Child
    WARNING: Stack unwind information not available. Following frames may be wrong.
    09a8fa2c 780119ab 09a8fad4 00000000 09a8faa8 MSVCRT!strnicmp+0x92
    09a8fa40 7801197c 09a8fad4 00000000 6d7044fd MSVCRT!stricmp+0x3c
    09a8fa80 6e5a6ef6 09a8fad4 2193d68d 00e5e298 MSVCRT!stricmp+0xd
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 使用 Windbg 分析互锁可以使用一些特定的命令来查看和分析系统中的互锁信息。其中一些常用的命令如下: 1. !locks - 显示系统中所有的互斥体和自旋锁的信息。 2. !handle - 查看特定进程中的所有句柄。 3. !critsec - 查看特定互斥体的详细信息。 4. !dlk - 查看死锁信息。 5. k - 查看堆栈信息,可以查看调用 WaitForSingleObject() 和 WaitForMultipleObjects() 函数的线程。 还有一些第三方工具如: 1. SpinlockTracer 2. DeadlockDetective 建议配合参考资料学习使用,并在正式的debug场景中使用。 ### 回答2: 在Windbg中分析互锁步骤如下: 1. 打开目标进程:在Windbg中选择“文件”>“打开进程”或使用命令行打开目标进程。 2. 设置符号路径:在Windbg中选择“文件”>“符号文件路径”,将包含目标二进制文件和符号文件的目录添加到符号路径中。 3. 启用调试选项:在Windbg中选择“调试”>“调试选项”,启用调试器的相关选项,例如“调试输出”、“源代码路径”等。 4. 附加到目标进程:在Windbg中选择“调试”>“附加到进程”,选择目标进程并附加。 5. 设置断点:在Windbg中选择“调试”>“新建断点”,并根据需要设置互锁相关的断点。例如,可以设置在进入或离开互锁对象的互斥体函数处设置断点。 6. 运行目标进程:在Windbg中选择“调试”>“运行”,让目标进程运行到断点处。 7. 分析互锁:一旦目标进程到达断点,可以使用Windbg的调试命令和命令扩展来分析互锁。可以使用命令如“!locks”查看进程中的所有互锁对象,“!analyze -v”分析调用栈以查找互锁问题的根本原因等。 8. 调试完成:当分析完成后,可以选择继续运行目标进程或结束调试。 以上是使用Windbg分析互锁的基本步骤。在实际应用中,还可以根据具体情况使用其他Windbg调试命令和技术来深入分析和解决互锁问题。 ### 回答3: Windbg是一款Windows操作系统上的调试工具,可以用来分析和调试应用程序的问题。在分析互锁时,以下是一些基本步骤: 1. 打开Windbg工具,并使用`file`命令加载需要分析的应用程序的可执行文件。 2. 使用`g`命令运行应用程序,使其在Windbg中开始运行。 3. 在应用程序出现问题的地方设置断点,可以使用`bp`命令设置断点,然后运行应用程序。 4. 当应用程序运行到断点处时,可以使用`!locks`命令来查看当前进程中的所有互锁对象。该命令将显示互锁对象的名称、所属线程、当前状态以及等待该互锁对象的线程列表等信息。 5. 使用`kb`命令查看当前线程的堆栈跟踪,确定哪些线程正在等待互锁对象,以及导致互锁的原因。 6. 使用`~~[数字]s`命令查看指定线程的堆栈跟踪,可以从中找出可能的问题代码。 7. 使用`!analyse -v`命令对问题进行进一步分析,该命令可以提供更多的调试信息,帮助定位问题。 8. 根据分析结果,可以在代码中找出可能存在的资源竞争或死锁问题。根据具体情况,可以修改代码、添加同步机制或者调整互锁的顺序等,以解决互锁问题。 以上是使用Windbg分析互锁的基本步骤,使用这些命令和功能可以快速定位和解决互锁问题,提高应用程序的稳定性和性能。在实际使用中,可以根据具体情况使用其他命令和调试技巧来深入分析问题

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值