代码之家  ›  专栏  ›  技术社区  ›  Patrick

DebugBreak的行为在非托管和混合(非托管+托管)应用程序之间有什么不同?

  •  1
  • Patrick  · 技术社区  · 15 年前

    使用以下简单的源代码(命名它测试.cpp):

    #include <windows.h>
    
    void main()
    {
    DebugBreak();
    }
    

    使用以下命令编译并链接:

    cl /MD /c test.cpp
    link /debug test.obj
    

    如果测试.EXE现在运行(在64位Windows 7系统上),您将看到以下对话框:

    DebugBreak in unmanaged application

    现在添加以下源文件(命名为test2.cpp):

    void hello()
    {
    }
    

    并将其与第一个源代码进行编译和链接,如下所示:

    cl /MD /c       test.cpp
    cl /MD /c /clr  test2.cpp
    link test.obj test2.obj
    

    请注意,我们甚至没有调用hello函数,只是将它链接了进来。

    现在快跑测试.EXE同样(在同一个64位Windows7系统上)。与上面显示的对话框不同,您可以看到:

    DebugBreak in mixed-mode application

    为什么会这样?我怎样才能重新恢复以前的DebugBreak行为呢? 这可能是Windows7或64位特定的行为吗?

    有一句话可以说明我为什么要使用DebugBreak:我们有一个自定义的assert框架(类似于John Robbin的《调试Windows应用程序》一书中的SuperAssert),我使用DebugBreak函数,这样如果出现问题,开发人员就可以跳转到调试器(或者打开一个新的调试器)。现在只有简单的弹出窗口,不可能再跳转到调试器了。

    编辑: 这是第二个测试中的调用堆栈(简单对话框):

    ntdll.dll!_NtRaiseHardError@24()  + 0x12 bytes  
    ntdll.dll!_NtRaiseHardError@24()  + 0x12 bytes  
    clrjit.dll!Compiler::compCompile()  + 0x5987 bytes  
    clr.dll!RaiseFailFastExceptionOnWin7()  + 0x6b bytes    
    clr.dll!WatsonLastChance()  + 0x1b8 bytes   
    clr.dll!InternalUnhandledExceptionFilter_Worker()  + 0x29c bytes    
    clr.dll!InitGSCookie()  + 0x70062 bytes 
    clr.dll!__CorExeMain@0()  + 0x71111 bytes   
    msvcr100_clr0400.dll!@_EH4_CallFilterFunc@8()  + 0x12 bytes 
    msvcr100_clr0400.dll!__except_handler4_common()  + 0x7f bytes   
    clr.dll!__except_handler4()  + 0x20 bytes   
    ntdll.dll!ExecuteHandler2@20()  + 0x26 bytes    
    ntdll.dll!ExecuteHandler@20()  + 0x24 bytes 
    ntdll.dll!_KiUserExceptionDispatcher@8()  + 0xf bytes   
    KernelBase.dll!_DebugBreak@0()  + 0x2 bytes 
    test_mixed.exe!01031009()   
    

    ntdll.dll!_ZwWaitForMultipleObjects@20()  + 0x15 bytes  
    ntdll.dll!_ZwWaitForMultipleObjects@20()  + 0x15 bytes  
    kernel32.dll!_WaitForMultipleObjectsExImplementation@20()  + 0x8e bytes 
    kernel32.dll!_WaitForMultipleObjects@16()  + 0x18 bytes 
    kernel32.dll!_WerpReportFaultInternal@8()  + 0x124 bytes    
    kernel32.dll!_WerpReportFault@8()  + 0x49 bytes 
    kernel32.dll!_BasepReportFault@8()  + 0x1f bytes    
    kernel32.dll!_UnhandledExceptionFilter@4()  + 0xe0 bytes    
    ntdll.dll!___RtlUserThreadStart@8()  + 0x369cc bytes    
    ntdll.dll!@_EH4_CallFilterFunc@8()  + 0x12 bytes    
    ntdll.dll!ExecuteHandler2@20()  + 0x26 bytes    
    ntdll.dll!ExecuteHandler@20()  + 0x24 bytes 
    ntdll.dll!_KiUserExceptionDispatcher@8()  + 0xf bytes   
    KernelBase.dll!_DebugBreak@0()  + 0x2 bytes 
    test_native.exe!00af1009()  
    

    不同之处在于ntdll.dll!执行handler2@20。在非.net应用程序中,它调用 ntdll.dll!@_EH4_CallFilterFunc . 在.net应用程序中是调用 clr.dll!__except_handler4 .

    1 回复  |  直到 15 年前
        1
  •  2
  •   Patrick    15 年前

    http://www.codeproject.com/KB/debug/DebugBreakAnyway.aspx

    除了编写DebugBreak之外,您还必须将DebugBreak调用嵌入到\uuu try/\uu except构造之间,如下所示:

    __try
       {
       DebugBreak();
       }
    __except (UnhandledExceptionFilter(GetExceptionInformation()))
       {
       }
    

    显然,UnhandledExceptionFilter函数默认处理DebugBreak异常,这在混合模式应用程序中似乎被否决了。

    现在你又回到原来的对话。

    推荐文章