Existe um portátil equivalente a DebugBreak () / __ DebugBreak?
-
05-07-2019 - |
Pergunta
Em MSVC, DebugBreak () ou __ DebugBreak causa um depurador para quebrar. Em x86 é equivalente a escrever "_asm int 3", em x64 é algo diferente. Ao compilar com gcc (ou qualquer outro compilador padrão) eu quero fazer uma pausa no depurador também. Existe uma função independente de plataforma ou intrínseca? Eu vi o XCode questão sobre isso, mas ele doesn' t parecem bastante portátil.
Sidenote: Eu quero principalmente para implementar ASSERT com isso, e eu entendo que eu posso usar assert () para isso, mas eu também quero escrever DEBUG_BREAK ou algo no código
.Solução
O que sobre a definição de uma macro condicional com base em #ifdef que se expande para diferentes construções baseado na arquitetura ou plataforma atual.
Algo como:
#ifdef _MSC_VER
#define DEBUG_BREAK __debugbreak()
#else
...
#endif
Este seria expandida pelo pré-processador a instrução depurador quebra correta baseado na plataforma onde o código é compilado. Desta forma, você sempre use DEBUG_BREAK
em seu código.
Outras dicas
Um método que é portável para a maioria dos sistemas POSIX é a seguinte:
raise(SIGTRAP);
GCC tem uma função interna chamada __builtin_trap
que você pode ver aqui , no entanto, assume-se que pára a execução de código Uma vez que este é alcançado.
você deve garantir que a chamada __builtin_trap()
é condicional, caso contrário, nenhum código será emitido depois.
este post alimentada por todos os 5 minutos de teste, YMMV.
Isto parece uma biblioteca compat apropriado https://github.com/scottt/debugbreak
Acabei de adicionar um módulo para portátil de trechos (uma coleção de trechos de domínio público de código portátil) para fazer isso. Não é 100% portátil, mas deve ser bastante robusto:
-
__builtin_debugtrap
para algumas versões do clang (identificado com__has_builtin(__builtin_debugtrap)
) - Em MSVC e Intel C ++ Compiler C /:
__debugbreak
- Para ARM C C ++ Compiler /:
__breakpoint(42)
- Para x86 / x86_64, montagem:
int $03
- Para ARM Thumb, montagem:
.inst 0xde01
- Para ARM AArch64, montagem:
.inst 0xd4200000
- Para outro braço, montagem:
.inst 0xe7f001f0
- Para Alpha, montagem:
bpt
- Para C não-hospedado com GCC (ou algo que se disfarça como ele),
__builtin_trap
- Caso contrário, incluem
signal.h
e- Se
defined(SIGTRAP)
(ou seja, POSIX),raise(SIGTRAP)
- Caso contrário,
raise(SIGABRT)
- Se
No futuro, o módulo no portátil de trechos podem expandir para incluir outra lógica e eu provavelmente vou esquecer de atualizar esta resposta, então você deve olhar lá para atualizações. É de domínio público (CC0), tão à vontade para roubar o código.
Se você considerar assert (x) o suficiente portátil, assert (false) parece ser a solução portátil óbvia para o problema.
Se você está tentando depurar uma condição relacionada com o acidente, o bom e velho abort moda () irá dar-lhe uma pilha de chamadas na maioria das plataformas. Desvantagem é que você não pode continuar a partir do PC atual, que você provavelmente não quer fazer de qualquer maneira.
Em vez de utilizar quebras 'normais' de depuração, por que não usar um dos seguintes, como uma divisão por zero:
int iCrash = 13 / 0;
ou dereference um ponteiro NULL:
BYTE bCrash = *(BYTE *)(NULL);
Pelo menos esta é portátil accross muitas plataformas / arquiteturas.
Em muitos depuradores você pode especificar qual ação você deseja realizar sobre o que exceções para que possa agir em conformidade quando um dos itens acima é atingido (como a execução de pausa, ala um "int 3" instrução) e uma exceção é gerada.
#define __debugbreak() \
do \
{ static bool b; \
while (!b) \
sleep(1); \
b = false; \
} while (false)
Quando o processo está dormindo, você pode anexar um depurador ao processo, altere a b variável para quebrar o ciclo e fazer a sua coisa. Este código pode não funcionar em uma compilação otimizada!