Есть ли переносимый эквивалент DebugBreak()/__ debugbreak?
В MSVC, DebugBreak() или __debugbreak вызывают сбой отладчика. На x86 это эквивалентно написанию "_asm int 3", на x64 это что-то другое. При компиляции с помощью gcc (или любого другого стандартного компилятора) я также хочу сделать разрыв в отладчике. Есть ли независимая от платформы функция или встроенная? Я видел вопрос XCode об этом, но он не выглядит достаточно портативным.
Sidenote: Я в основном хочу реализовать ASSERT с этим, и я понимаю, что могу использовать assert() для этого, но я также хочу написать DEBUG_BREAK или что-то еще в коде.
Ответы
Ответ 1
Как определить условный макрос на основе #ifdef, который расширяется до разных конструкций на основе текущей архитектуры или платформы.
Что-то вроде:
#ifdef _MSC_VER
#define DEBUG_BREAK __debugbreak()
#else
...
#endif
Это будет расширен препроцессором правильная команда отладки отладчика, основанная на платформе, где компилируется код. Таким образом, вы всегда используете DEBUG_BREAK
в своем коде.
Ответ 2
Метод, переносимый большинством систем POSIX:
raise(SIGTRAP);
Ответ 3
GCC имеет встроенную функцию с именем __builtin_trap
, которую вы можете увидеть здесь однако предполагается, что выполнение кода останавливается после достижения этого.
вы должны убедиться, что вызов __builtin_trap()
условный, иначе после него не будет выдан код.
этот пост заправляется всеми 5 минутами тестирования, YMMV.
Ответ 4
Это выглядит как соответствующая библиотека совместимости https://github.com/scottt/debugbreak
Ответ 5
Если вы считаете assert (x) достаточно переносимым, assert (false) представляется очевидным переносным решением вашей проблемы.
Ответ 6
Если вы пытаетесь отладить состояние, связанное с сбоем, хороший старомодный abort() даст вам стек вызовов на большинстве платформ. Недостатком является то, что вы не можете продолжать работу с текущим ПК, который, вероятно, вы все равно не хотите делать.
http://www.cplusplus.com/reference/cstdlib/abort/
Ответ 7
Я просто добавил модуль в portable-snippets (набор фрагментов общедоступного домена переносимого кода), чтобы сделать это. Это не на 100% портативно, но должно быть довольно надежно:
-
__builtin_debugtrap
для некоторых версий clang (определяется с помощью __has_builtin(__builtin_debugtrap)
) - На MSVC и компиляторе Intel C/C++:
__debugbreak
- Для компилятора ARM C/C++:
__breakpoint(42)
- Для x86/x86_64 сборка:
int $03
- Для большого пальца ARM, сборка:
.inst 0xde01
- Для ARM AArch64, сборка:
.inst 0xd4200000
- Для других ARM, сборка:
.inst 0xe7f001f0
- Для Альфы, сборка:
bpt
- Для не размещенного C с GCC (или что-то, что маскируется под него),
__builtin_trap
- В противном случае,
signal.h
и - Если
defined(SIGTRAP)
(т.е. POSIX), raise(SIGTRAP)
- В противном случае
raise(SIGABRT)
В будущем модуль в переносимых фрагментах может расширяться, чтобы включать другую логику, и я, вероятно, забуду обновить этот ответ, так что вы должны искать там обновления. Это общественное достояние (CC0), поэтому не стесняйтесь воровать код.
Ответ 8
#define __debugbreak() \
do \
{ static bool b; \
while (!b) \
sleep(1); \
b = false; \
} while (false)
Когда процесс спал, вы можете присоединить отладчик к процессу, изменить переменную b, чтобы разбить цикл и выполнить свою задачу. Этот код может не работать в оптимизированной сборке!
Ответ 9
Вместо использования "нормальных" отладочных разрывов, почему бы не использовать одно из следующего, например, деление на ноль:
int iCrash = 13 / 0;
или разыщите указатель NULL:
BYTE bCrash = *(BYTE *)(NULL);
По крайней мере, это переносится на многих платформах/архитектурах.
Во многих отладчиках вы можете указать, какое действие вы хотите выполнить на каких исключениях, чтобы вы могли действовать соответственно, когда один из вышеперечисленных ударил (например, pause execute, ala a "int 3" ) и генерируется исключение.