Comportement des DebugBreak diffère entre l'application et non géré mixte (géré non géré +)?
-
26-09-2019 - |
Question
Prenez la source simple (nommez-test.cpp) suivant:
#include <windows.h>
void main()
{
DebugBreak();
}
compiler et lier cela en utilisant les commandes suivantes:
cl /MD /c test.cpp
link /debug test.obj
Si TEST.EXE est maintenant exécuté (sur un système Windows 7 64 bits), vous obtenez la fenêtre suivante:
Maintenant, ajoutez le fichier source suivante (nommez-test2.cpp):
void hello()
{
}
compiler et lier cela avec la première source, comme ceci:
cl /MD /c test.cpp
cl /MD /c /clr test2.cpp
link test.obj test2.obj
Notez que nous ne même pas appeler le bonjour fonction, nous juste Linked dans.
Maintenant, exécutez TEST.EXE à nouveau (sur le même système Windows 7 64 bits). Au lieu de la boîte de dialogue indiqué ci-dessus, vous obtenez ceci:
Apparemment, la liaison dans le cadre .Net fait se comportent différemment DebugBreak. Pourquoi est-ce? Et comment puis-je l'ancien comportement DebugBreak à nouveau? Est-ce peut-être un comportement spécifique bits Windows 7 64 ou?
A côté remarque à préciser pourquoi je veux utiliser DebugBreak: nous avons un assert-cadre personnalisé (quelque chose comme le SuperAssert de débogage d'applications Windows livre de John Robbin), et utiliser la fonction DebugBreak afin que le développeur peut sauter dans le débogueur (ou ouvrir un nouveau débogueur) s'il y a un problème. Maintenant, il n'y a que le menu contextuel simple et sans possibilité de sauter au débogueur plus.
En tant que solution de rechange que je pourrais effectuer une division par zéro ou une écriture adresse non valide, mais je trouve cela une solution moins propre.
EDIT: Ceci est la pile d'appel dans le second test (la simple boîte de dialogue):
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()
Ceci est la pile d'appel dans le premier test (dialogue avec des choix « fermer » et « debug »):
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()
La différence commence à ntdll.dll!Executehandler2@20. Dans une application non-.net appelle ntdll.dll!@_EH4_CallFilterFunc
. Dans une application .net est clr.dll!__except_handler4
appels.
La solution
J'ai trouvé la solution sur la page suivante: http: //www.codeproject. com / KB / debug / DebugBreakAnyway.aspx .
Au lieu de simplement écrire DebugBreak, vous devez intégrer l'appel DebugBreak entre un __try / __ sauf construction, comme ceci:
__try
{
DebugBreak();
}
__except (UnhandledExceptionFilter(GetExceptionInformation()))
{
}
Apparemment, les poignées de fonction UnhandledExceptionFilter l'exception DebugBreak par défaut, ce qui semble être infirmée dans un appliation mode mixte.
Maintenant, vous obtenez la boîte de dialogue d'origine à nouveau.