Comportamiento de DebugBreak diferencia entre la aplicación no administrado y mezclado (no administrado + administrado)?

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

  •  26-09-2019
  •  | 
  •  

Pregunta

Tome la siguiente fuente simple (nombre que test.cpp):

#include <windows.h>

void main()
{
DebugBreak();
}

compilación y enlace que esta usando los siguientes comandos:

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

Si TEST.EXE es ahora dirigido (en un sistema Windows 7 64-bit), se obtiene el siguiente cuadro de diálogo:

DebugBreak en aplicación no administrada

Ahora agregue el siguiente archivo de origen (nombre que test2.cpp):

void hello()
{
}

Y compilación y enlace que esto junto con la primera fuente, de esta manera:

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

Tenga en cuenta que nosotros ni siquiera llamar a la hola-función, que sólo ha unido de.

Ahora ejecute TEST.EXE de nuevo (en el mismo sistema de 64 bits Windows 7). En lugar del diálogo que se muestra más arriba, se obtiene lo siguiente:

DebugBreak en la solicitud de modo mixto

Al parecer, la vinculación en el marco .Net hace DebugBreak se comportan de manera diferente. ¿Por qué es esto? Y cómo puedo obtener la parte posterior comportamiento DebugBreak edad de nuevo? Es esta, posiblemente, un comportamiento específico de Windows 7 o de 64 bits?

Un lado observación para dejar claro por qué quiero usar DebugBreak: tenemos una aserción-marco personalizado (algo así como el SuperAssert del libro de depuración de aplicaciones de Windows de John Robbin), y utilizo la función DebugBreak por lo que el desarrollador puede saltar en el depurador (o abrir un nuevo depurador) si hay un problema. Ahora sólo existe el emergente simple y sin posibilidad de saltar al depurador más.

Como una solución alternativa que pudiera realizar una división por cero o una escritura en dirección no válida, pero encuentro esto una solución menos limpia.

EDIT: Esta es la pila de llamadas en la segunda prueba (el cuadro de diálogo simple):

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

Esta es la pila de llamadas en la primera prueba (de diálogo con las opciones de "cerrar" y "depuración"):

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 diferencia comienza en ntdll.dll!Executehandler2@20. En una aplicación que llama non-.net ntdll.dll!@_EH4_CallFilterFunc. En una aplicación .NET es clr.dll!__except_handler4 llamadas.

¿Fue útil?

Solución

He encontrado la solución en la siguiente página: http: //www.codeproject. com / KB / debug / DebugBreakAnyway.aspx .

En lugar de simplemente escribir DebugBreak, hay que integrar la llamada DebugBreak entre un __try / __ excepto la construcción, así:

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

Al parecer, las asas de función UnhandledExceptionFilter la excepción DebugBreak por defecto, lo que parece ser revocada en una appliation de modo mixto.

Ahora se obtiene el diálogo original de nuevo otra vez.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top