1

次の単純なソース(test.cppという名前)を使用します。

#include <windows.h>

void main()
{
DebugBreak();
}

次のコマンドを使用して、これをコンパイルしてリンクします。

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

TEST.EXEが(64ビットのWindows 7システムで)実行されると、次のダイアログが表示されます。

管理されていないアプリケーションでのDebugBreak

次に、次のソースファイルを追加します(test2.cppという名前を付けます)。

void hello()
{
}

そして、これをコンパイルして、次のように最初のソースとリンクします。

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

hello-functionを呼び出さず、リンクしただけであることに注意してください。

次に、TEST.EXEを再度実行します(同じ64ビットWindows 7システムで)。上記のダイアログの代わりに、次のように表示されます。

混合モードアプリケーションでのDebugBreak

どうやら、.Net Frameworkでリンクすると、DebugBreakの動作が異なります。どうしてこれなの?そして、どうすれば古いDebugBreakの動作を元に戻すことができますか?これはおそらくWindows7または64ビット固有の動作ですか?

DebugBreakを使用する理由を明確にするための補足:カスタムassert-framework(JohnRobbinのDebuggingWindows ApplicationsブックのSuperAssertのようなもの)があり、開発者がデバッガーにジャンプできるようにDebugBreak関数を使用します(または、問題がある場合は、新しいデバッガーを開きます)。これで、単純なポップアップのみが表示され、デバッガーにジャンプすることはできなくなりました。

別の解決策として、ゼロ除算または無効なアドレスへの書き込みを実行することもできますが、これはあまりクリーンな解決策ではありません。

編集: これは2番目のテスト(単純なダイアログ)の呼び出しスタックです:

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です。

4

1 に答える 1

2

次のページで解決策を見つけました:http://www.codeproject.com/KB/debug/DebugBreakAnyway.aspx

DebugBreakを記述するだけでなく、次のように__try/__except構造の間にDebugBreak呼び出しを埋め込む必要があります。

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

どうやら、UnhandledExceptionFilter関数は、デフォルトでDebugBreak例外を処理します。これは、混合モードのアプリケーションでは無効になっているようです。

これで、元のダイアログが再び表示されます。

于 2010-09-10T15:53:55.570 に答える