DebugBreak在非托管和混合(非托管+托管)应用程序之间有所不同?
Posted yilang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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异常,在混合模式应用中,该异常似乎被否决。现在又得到了原来的对话框。
以上是关于DebugBreak在非托管和混合(非托管+托管)应用程序之间有所不同?的主要内容,如果未能解决你的问题,请参考以下文章
HRESULT、DWORD 和 HANDLE 在非托管代码中是啥意思?
HRESULT、DWORD 和 HANDLE 在非托管代码中是啥意思?
在托管进程中使用 EventWaitHandle 和在非托管进程中使用 WaitForSingleObject 进行跨进程同步