Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/141.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 是否有类似于DebugBreak()/\uu DebugBreak的可移植版本?_C++_Portability_Debugbreak - Fatal编程技术网

C++ 是否有类似于DebugBreak()/\uu DebugBreak的可移植版本?

C++ 是否有类似于DebugBreak()/\uu DebugBreak的可移植版本?,c++,portability,debugbreak,C++,Portability,Debugbreak,或导致调试器中断。在x86上,它相当于写入“_asmint 3”,在x64上则有所不同。当使用gcc(或任何其他标准编译器)编译时,我也想进行一次中断调试器。是否存在独立于平台的功能或固有功能?我看到了这方面的进展,但它似乎不够便携 旁注:我主要想用它实现ASSERT,我知道我可以使用ASSERT(),但我还想在代码中写入DEBUG_BREAK或其他内容。如何定义一个基于#ifdef的条件宏,该宏根据当前的体系结构或平台扩展到不同的结构 比如: #ifdef _MSC_VER #define D

或导致调试器中断。在x86上,它相当于写入“_asmint 3”,在x64上则有所不同。当使用gcc(或任何其他标准编译器)编译时,我也想进行一次中断调试器。是否存在独立于平台的功能或固有功能?我看到了这方面的进展,但它似乎不够便携


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

如何定义一个基于#ifdef的条件宏,该宏根据当前的体系结构或平台扩展到不同的结构

比如:

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

预处理器将根据编译代码的平台使用正确的调试器中断指令来扩展这一功能。通过这种方式,您总是在代码中使用
DEBUG\u BREAK

GCC有一个名为
\u builtin\u trap
的内置函数,您可以看到该函数,但是假设一旦达到该函数,代码执行就会停止

您应该确保
\u builtin\u trap()
调用是有条件的,否则之后不会发出任何代码


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

为什么不使用“正常”调试中断,而不是使用以下之一,比如除以零:

int iCrash = 13 / 0;
或取消对空指针的引用:

BYTE bCrash = *(BYTE *)(NULL);
至少在许多平台/架构中都是可移植的


在许多调试器中,您可以指定要在哪些异常上执行什么动作,这样当上面一个命中时(如暂停执行、ALLAN)INT 3“指令”和异常生成时,您可以相应地动作。

< P>如果您考虑<代码>断言(x)< /C>足够便携,<代码>断言(false)似乎是解决您问题的显而易见的可移植解决方案。

对于大多数POSIX系统来说,可移植的方法是:

raise(SIGTRAP);

这看起来像是一个合适的compat库

如果您试图调试与崩溃相关的条件,好的老式abort()将在大多数平台上为您提供一个调用堆栈。不利的一面是,你无法从当前的PC继续,这可能是你无论如何都不想做的

当进程处于睡眠状态时,您可以将调试器附加到进程,更改变量b以中断循环并执行您的操作。此代码可能无法在优化版本中工作

我刚刚添加到(一个可移植代码的公共域片段集合)来实现这一点。它不是100%可移植的,但应该非常健壮:

  • \uuuuu内置调试陷阱
    用于某些版本的clang(用
    \uuu标识为已内置(\uuuu内置调试陷阱)
  • 在MSVC和英特尔C/C++编译器上:
    \uu debugbreak
  • 对于ARM C/C++编译器:
    \u断点(42)
  • 对于x86/x86_64,程序集:
    int3
  • 对于臂拇指,组件:
    .inst 0xde01
  • 对于ARM AArch64,组件:
    .inst 0xd42000
  • 对于其他臂,组件:
    .inst 0xe7f001f0
  • 对于Alpha,组件:
    bpt
  • 对于带有GCC(或伪装成它的东西)的非托管C,
    \uuuu内置陷阱
  • 否则,包括
    signal.h
    • 如果
      已定义(SIGTRAP)
      (即POSIX),
      升起(SIGTRAP)
    • 否则,
      rise(SIGABRT)

将来,可移植代码段中的模块可能会扩展到包含其他逻辑,我可能会忘记更新这个答案,所以您应该在那里查找更新。这是公共域(CC0),所以可以随意窃取代码。

这似乎是一个很好的、可移植的解决方案:

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

    __debugbreak, 

在i386和x86_64上以及在ARM上实现

    __asm__ volatile(".inst 0xe7f001f0");

此外,还记录了GDB中单步跳过断点的标题中提到的问题的一些解决方法,以及在stepi或cont卡住的平台上扩展GDB的Python脚本。脚本将debugbreak步骤debugbreak continue添加到GDB中。

FWIW,这些解决方案都无法在使用NRF Connect SDK的nRF9160上运行。这是一个SEGGER Embedded Studio for ARM(北欧版)环境,使用
ARM none eabi gcc
编译器

其他答案中提到的
debug trap.h
debugbreak.h
内置陷阱()
都会导致“未定义的操作码”和硬故障(或调试监视器故障,但结果相同),并且没有有用的程序计数器、堆栈帧或其他可调试信息

最后,这个替代品起了作用。我从另一个神秘的北欧图书馆中得到了它,在那里它被称为
NRF\u断点

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

在构建时,包含的是
\uuu GNUC\uuu
路径,因此
\uuu asm\uuuu(“BKPT 0”)
就是所需的全部内容。

实际上我这里有一块板,可以很高兴地进行空指针解引用。被零除可能更安全。有趣。当这种异常发生时,它将如何继续?对于int 3,VS调试器知道如何继续,我只需要按Go(F5),或者如果我想禁用该位置上的断言,我可以使用这个技巧-这里有类似的东西吗?在大多数嵌入式系统上,取消引用NULL(=0)实际上不是一个错误,因为地址0通常是一个真实的内存位置。在ARM内核上,它是向量表。请避免使用这种解决方法。这是一个难以置信的安全风险,它使堆栈处于不一致的状态,并且取决于可用于攻击的应用程序!在大多数情况下都很好,但在发布代码中没有太大帮助。是的,有时我不得不调试发布代码…
assert
根本不是一个合适的解决方案,因为它通常不允许程序继续执行。
raise(SIGTRAP)
在gcc/Linu上对我来说非常好用
    __asm__ volatile(".inst 0xe7f001f0");
#if defined(__GNUC__)
    __asm__("BKPT 0");
#else
    __BKPT(0)
#endif