• DebugBreak在非托管和混合(非托管+托管)应用程序之间有所不同?


    采用以下简单的源代码(将其命名为test.cpp):

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

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

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

    如果TEST.EXE现在运行(在64位Windows 7系统上),将显示以下对话框:

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

    void hello()
    {
    }
    编译并将其与第一个源链接在一起,如下所示:
    cl /MD /c       test.cpp
    cl /MD /c /clr  test2.cpp
    link test.obj test2.obj

    注意,我们甚至都没有调用hello函数,只是将其链接进来。现在再次运行TEST.EXE(在相同的64位Windows 7系统上)。您将得到以下结果,而不是上面显示的对话框:

    显然,.Net framework中的链接使DebugBreak的行为有所不同。这是为什么?我怎样才能恢复旧的DebugBreak行为呢?这可能是Windows 7或64位特定行为吗?
    为了说明我为什么要使用DebugBreak,需要补充一点:我们有一个自定义的assert框架(类似于John Robbin的《调试Windows应用程序》一书中的supersassert),并且我使用了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!ExecuteHandler2@20()开始。在非.net应用程序中,它调用ntdll.dll!@_EH4_CallFilterFunc。在.net应用程序中是调用clr.dll!__except_handler4()

    我在下面的页面找到了解决方案:ttp://www.codeproject.com/KB/debug/DebugBreakAnyway.aspx.

    除了编写DebugBreak之外,还必须在_try/_except之间嵌入DebugBreak调用,如下所示:

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

    显然,UnhandledExceptionFilter函数默认处理DebugBreak异常,在混合模式应用中,该异常似乎被否决。现在又得到了原来的对话框。

  • 相关阅读:
    equals()与=的区别
    HashTable和HashMap的区别
    shell高级用法——磁盘管理 创建虚拟的磁盘映射到一个文件
    shell妙用之——dd命令合并多个烧录文件为一个flash镜像
    自动解包ROM 文件获取uboot,uboot-spl ,uImage, rootfs.tar.gz 并烧写SD卡
    运用层通过shell脚本直接操控gpio
    shell脚本之位运算+for循环+返回值承接+shell小数运算
    shell函数递归调用实现目录的对比拷贝
    用debootstrip制作debian环境的rootfs
    shell命令的高级使用之---选择性copy
  • 原文地址:https://www.cnblogs.com/yilang/p/12366145.html
Copyright © 2020-2023  润新知