是否有一个可移植的等效于DebugBreak()/ __ debugbreak?

时间:2008-10-06 08:57:53

标签: c++ portability debugbreak

在MSVC中,DebugBreak()__debugbreak会导致调试程序中断。在x86上它相当于写“_asm int 3”,在x64上它是不同的东西。在使用gcc(或任何其他标准编译器)进行编译时,我也想进入调试器。是否存在平台无关功能或内在功能?我看到了XCode question,但它似乎不够便携。

旁注:我主要想用它来实现ASSERT,我知道我可以使用assert(),但我也想在代码中编写DEBUG_BREAK或其他内容。

11 个答案:

答案 0 :(得分:38)

可移植到大多数POSIX系统的方法是:

raise(SIGTRAP);

答案 1 :(得分:12)

如何基于#ifdef定义基于当前体系结构或平台扩展到不同构造的条件宏。

类似的东西:

#ifdef _MSC_VER
#define DEBUG_BREAK __debugbreak()
#else
...
#endif

这将由预处理器根据编译代码的平台扩展正确的调试器中断指令。这样,您始终可以在代码中使用DEBUG_BREAK

答案 2 :(得分:12)

GCC有一个名为__builtin_trap的内置函数,您可以看到here,但是假设代码执行在达到此值后暂停。

确保__builtin_trap()调用是有条件的,否则后面不会发出任何代码。

这篇文章是在YMMV的所有5分钟测试的推动下推动的。

答案 3 :(得分:9)

这看起来像是一个合适的compat库https://github.com/scottt/debugbreak

答案 4 :(得分:6)

我刚刚将a module添加到portable-snippets(可移植代码的公共域代码段的集合)来执行此操作。它不是100%可移植的,但它应该非常强大:

    对于某些版本的clang(标有__builtin_debugtrap),
  • __has_builtin(__builtin_debugtrap)
  • 在MSVC和Intel C / C ++编译器上:__debugbreak
  • 对于ARM C / C ++编译器:__breakpoint(42)
  • 对于x86 / x86_64,程序集:int $03
  • 对于ARM Thumb,程序集:.inst 0xde01
  • 对于ARM AArch64,程序集:.inst 0xd4200000
  • 对于其他ARM,程序集:.inst 0xe7f001f0
  • 对于Alpha,汇编:bpt
  • 对于使用GCC的非托管C(或伪装成GCC的东西),__builtin_trap
  • 否则,请添加signal.h
    • 如果defined(SIGTRAP)(即POSIX),raise(SIGTRAP)
    • 否则,raise(SIGABRT)

将来,便携式片段中的模块可能会扩展到包含其他逻辑,我可能会忘记更新此答案,因此您应该查看更新。它是公共领域(CC0),所以随意窃取代码。

答案 5 :(得分:4)

如果你认为assert(x)足够便携,那么assert(false)似乎是你问题的明显可移植解决方案。

答案 6 :(得分:1)

如果您正在尝试调试与崩溃相关的条件,那么老式的abort()将在大多数平台上为您提供调用堆栈。缺点是您不能继续使用当前的PC,您可能不想这样做。

http://www.cplusplus.com/reference/cstdlib/abort/

答案 7 :(得分:1)

对于这个问题,这似乎是一个非常好的便携式解决方案: https://github.com/scottt/debugbreak

引用的存储库(debugbreak.h)中提供的标头封装了MSVC的

    __debugbreak, 

    __asm__ volatile("int $0x03");

在i386和x86_64上,并且在ARM上实现

    __asm__ volatile(".inst 0xe7f001f0");

并记录了一些标题中指出的问题的变通方法,这些问题可单步通过GDB中的断点,另外还提供了Python脚本,用于在 stepi cont 卡住了。该脚本将 debugbreak-step debugbreak-continue 添加到GDB。

答案 8 :(得分:0)

FWIW,这些解决方案都不适用于使用 NRF Connect SDK 的 nRF9160。这是一个适用于 ARM(北欧版)环境的 SEGGER Embedded Studio,使用 arm-none-eabi-gcc 编译器。

其他答案中提到的debug-trap.hdebugbreak.h__builtin_trap()都导致“未定义操作码”和硬故障(或调试监视器故障,但结果是一样的) 并且没有有用的程序计数器、堆栈帧或其他可调试信息。

最后,这个替代品确实奏效了。我从其他一些神秘的北欧图书馆派生它,在那里它被称为 NRF_BREAKPOINT:

#if defined(__GNUC__)
    __asm__("BKPT 0");
#else
    __BKPT(0)
#endif

在构建时,包含的是 __GNUC__ 路径,因此 __asm__("BKPT 0") 就是全部所需。

答案 9 :(得分:-4)

不使用“普通”调试中断,为什么不使用以下之一,例如除以零:

int iCrash = 13 / 0;

或取消引用NULL指针:

BYTE bCrash = *(BYTE *)(NULL);

至少这可以在许多平台/架构中移植。

在许多调试器中,您可以指定要对哪些异常执行哪些操作,以便在执行上述操作之一时(例如暂停执行,ala“int 3”指令)并生成异常时可以相应地执行操作。 / p>

答案 10 :(得分:-4)

#define __debugbreak() \
do \
{       static bool b; \
        while (!b) \
                sleep(1); \
        b = false; \
} while (false)

当进程处于休眠状态时,您可以将调试器附加到进程,更改变量b以打破循环并执行您的操作。此代码可能无法在优化的构建中使用!