Comportamiento de DebugBreak diferencia entre la aplicación no administrado y mezclado (no administrado + administrado)?
-
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:
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:
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.
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.