Comportement des DebugBreak diffère entre l'application et non géré mixte (géré non géré +)?

StackOverflow https://stackoverflow.com/questions/3629783

  •  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:

DebugBreak en application non gérée

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:

DebugBreak dans l

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.

Était-ce utile?

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.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top