是否有任何理由不将assert() 包装在解析为gcc 中的__builtin_unreachable() 的宏中?

5 c++ optimization gcc assert

上下文:在这个答案中,我了解到 gcc__builtin_unreachable()可能会对性能产生一些令人惊讶的影响,因为看起来如下:

if(condition) __builtin_unreachable();
Run Code Online (Sandbox Code Playgroud)

被完全剥离,只要condition能保证没有任何副作用,就可以用作优化提示。

因此,我对此的立即反应是,我应该创建以下宏,并在我通常使用的任何地方都使用它assert(),因为在 an 内诱导代码的副作用assert()首先将是一个主要错误:

// TODO: add handling of other compilers as appropriate.
#if defined(__GNUC__) && defined(NDEBUG)
  #define my_assert(condition) \
    if(!(condition)) __builtin_unreachable()
#else 
  #define my_assert(condition) assert(condition)
#endif
Run Code Online (Sandbox Code Playgroud)

从标准的角度来看,这将在正常和构建之间创建功能划分NDEBUG,您可以提出一个论据,将该宏排除在assert(). 然而,由于无论如何,在断言失败的情况下,我的代码在功能上都会死在水中,因此从行为的角度来看,它是完全等效的。

所以我的问题是:任何人都可以想出一个不这样做的理由(除了涉及大量间接的断言之外)?

在你问之前,是的,我已经检查过 gcc 的行为是在构建中无效地放弃断言NDEBUG

Han*_*son 2

是的,有一个不使用它的理由。有些人使用以下结合了断言和异常(assert(x>0); if (!(x<0)) throw std::logic_error(".."))的防御性代码实践 - 请参阅此答案:

测试用例和断言语句

您的宏会默默地破坏发布版本的异常部分。

  • 我真的不喜欢这种做法,因为它混淆了编程错误和运行时错误。在我看来,这个断言没有必要存在。我的代码库不会受到此影响,但记住这一点是一件好事。 (2认同)
  • 我看不出那有什么价值。它似乎违背了“assert()”的目的,因为它对发布代码的运行时影响为零。如果您想要的话,也可以使用异常。 (2认同)