Подтвердить что ты не робот

Есть ли переносимый эквивалент DebugBreak()/__ debugbreak?

В MSVC, DebugBreak() или __debugbreak вызывают сбой отладчика. На x86 это эквивалентно написанию "_asm int 3", на x64 это что-то другое. При компиляции с помощью gcc (или любого другого стандартного компилятора) я также хочу сделать разрыв в отладчике. Есть ли независимая от платформы функция или встроенная? Я видел вопрос XCode об этом, но он не выглядит достаточно портативным.

Sidenote: Я в основном хочу реализовать ASSERT с этим, и я понимаю, что могу использовать assert() для этого, но я также хочу написать DEBUG_BREAK или что-то еще в коде.

4b9b3361

Ответ 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.

Ответ 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" ) и генерируется исключение.