Comportamento di DebugBreak diversa tra (gestito gestito +) applicazione non gestito e misti?

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

  •  26-09-2019
  •  | 
  •  

Domanda

Prendere la seguente origine semplice (lo chiama test.cpp):

#include <windows.h>

void main()
{
DebugBreak();
}

compilare e linkare questo utilizzando i seguenti comandi:

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

Se PROVA.EXE è ora gestito (su un sistema Windows 7 64-bit), si ottiene la seguente finestra di dialogo:

DebugBreak in applicazione non gestita

Ora aggiungere il seguente file di origine (chiamarlo test2.cpp):

void hello()
{
}

E compilare e linkare questo insieme con la prima fonte, in questo modo:

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

Si noti che non abbiamo nemmeno chiamare la funzione di ciao-, abbiamo appena legati in.

Ora eseguire nuovamente PROVA.EXE (sullo stesso sistema a 64 bit di Windows 7). Invece della finestra di dialogo mostrato sopra, si ottiene questo:

DebugBreak in applicazione in modalità mista

A quanto pare, il collegamento nel quadro Net rende DebugBreak comportano in modo diverso. Perchè è questo? E come posso ottenere di nuovo il vecchio DebugBreak comportamento indietro? È questo forse un comportamento specifico di Windows 7 o 64 bit?

Un lato-osservazione per chiarire il motivo per cui voglio usare DebugBreak: abbiamo un assert-quadro personalizzato (qualcosa di simile alla SuperAssert da applicazioni libro debug di Windows di John Robbin), e io uso la funzione DebugBreak modo lo sviluppatore può saltare in il debugger (o aprire un nuovo debugger) se c'è un problema. Ora c'è solo la semplice comparsa e nessuna possibilità di saltare al debugger più.

Come soluzione alternativa ho potuto eseguire una divisione per zero o una scrittura di indirizzo non valido, ma trovo questa una soluzione meno pulita.

Modifica Questo è lo stack di chiamate nella seconda prova (la semplice finestra di dialogo):

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()   

Questo è lo stack di chiamate nella prima prova (dialogo con le scelte "chiuso" e "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 differenza inizia nel ntdll.dll!Executehandler2@20. In un'applicazione non-.net chiama ntdll.dll!@_EH4_CallFilterFunc. In un'applicazione .NET è chiamate clr.dll!__except_handler4.

È stato utile?

Soluzione

ho trovato la soluzione nella seguente pagina: http: //www.codeproject. com / KB / debug / DebugBreakAnyway.aspx .

Invece di limitarsi a scrivere DebugBreak, è necessario incorporare la chiamata DebugBreak tra un __try / __ tranne la costruzione, in questo modo:

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

A quanto pare, la funzione maniglie UnhandledExceptionFilter l'eccezione DebugBreak di default, che sembra essere oltrepassato in un appliation modalità mista.

Ora si ottiene la finestra originale di nuovo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top