O comportamento do debugbreak difere entre o aplicativo não gerenciado e misto (não gerenciado+gerenciado)?

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

  •  26-09-2019
  •  | 
  •  

Pergunta

Pegue a seguinte fonte simples (Name It test.cpp):

#include <windows.h>

void main()
{
DebugBreak();
}

Compilar e vincular isso usando os seguintes comandos:

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

Se o test.exe agora estiver executado (em um sistema Windows 7 de 64 bits), você obtém a seguinte caixa de diálogo:

DebugBreak in unmanaged application

Agora adicione o seguinte arquivo de origem (Name It test2.cpp):

void hello()
{
}

E compilar e vincular isso com a primeira fonte, como esta:

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

Observe que nem chamamos a função de olá, apenas o vinculamos.

Agora execute test.exe novamente (no mesmo sistema Windows 7 de 64 bits). Em vez da caixa de diálogo mostrada acima, você entendeu:

DebugBreak in mixed-mode application

Aparentemente, a ligação na estrutura do .NET faz com que o Debugbreak se comporte de maneira diferente. Por que é isso? E como posso recuperar o comportamento do antigo debugbreak? Isso é possivelmente um comportamento específico do Windows 7 ou 64 bits?

Uma remark lateral para esclarecer por que eu quero usar o Debugbreak: temos um trabalho de frame assert personalizado (algo como o SuperAssest do livro de aplicativos de depuração de John Robbin), e eu uso a função Debugbreak para que o desenvolvedor possa entrar no depurador ( ou abrir um novo depurador) se houver um problema. Agora existe apenas o pop -up simples e nenhuma possibilidade de pular para o depurador.

Como uma solução alternativa, eu poderia executar uma divisão por zero ou uma gravação para o endereço inválido, mas acho isso uma solução menos limpa.

EDITAR:Esta é a pilha de chamadas no segundo teste (a caixa de diálogo simples):

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 é a pilha de chamadas no primeiro teste (diálogo com opções "Close" 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()  

A diferença começa em ntdll.dll!executehandler2@20. Em um aplicativo não -.net, ele chama ntdll.dll!@_EH4_CallFilterFunc. Em um aplicativo .NET é chamadas clr.dll!__except_handler4.

Foi útil?

Solução

Encontrei a solução na página seguinte: http://www.codeproject.com/kb/debug/debugbreakany.aspx.

Em vez de apenas escrever Debugbreak, você deve incorporar a chamada de depuração entre uma __Try/__, exceto a construção, assim:

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

Aparentemente, a função UNHLEDLEDEXCECTIONSFILTER lida com a exceção de depuração por padrão, que parece ser anulada em uma aplicação de modo misto.

Agora você recupera o diálogo original novamente.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top