在C / C ++中断言(false)的更好替代方法

shu*_*alo 2 c c++ debugging assert

目前,我写

assert(false);
Run Code Online (Sandbox Code Playgroud)

在我的代码永远无法到达的地方。一个非常C风格的示例是:

int findzero( int length, int * array ) {
  for( int i = 0; i < length; i++ )
    if( array[i] == 0 )
      return i;
  assert(false);
}
Run Code Online (Sandbox Code Playgroud)

一旦达到assert(false),我的编译器就会意识到程序已完成。但是,每当出于性能原因使用-DNDEBUG进行编译时,最后一个断言都会消失,并且编译器会警告执行将在没有return语句的情况下完成该函数。

如果已经达到了代码的一个所谓的无法到达的部分,那么完成程序的更好的替代方法是什么?解决方案应该

  • 被编译器识别并且不产生警告(如上述警告或其他警告)
  • 甚至允许自定义错误消息。

无论是现代C ++还是90s C,我都对解决方案特别感兴趣。

Lig*_*ica 6

替换您的assert(false)内容正是“无法访问的”内置功能的目的。

它们在语义上等同于您对的使用assert(false)。实际上,VS的拼写非常相似。

GCC / C语/英特尔:

__builtin_unreachable()
Run Code Online (Sandbox Code Playgroud)

MSVS:

 __assume(false)
Run Code Online (Sandbox Code Playgroud)

不管NDEBUG(与assert)或优化级别如何,它们都有效。

您的编译器,尤其是具有上述内置功能的编译器,也可能与您的一起使用assert(false),它的头是理解您承诺永远无法实现部分功能。它可以使用它在某些代码路径上执行一些优化,并且由于您已经保证它是故意的,因此它将使有关返回缺失的警告静音。

需要权衡的是,语句本身具有未定义的行为(就像已经存在并从函数末尾流出一样)。在某些情况下,您可能希望考虑引发异常(或返回一些“错误代码”值),或者std::abort()如果想终止程序,则调用(在C ++中)。


有一个建议(P0627R0),将其作为标准属性添加到C ++中。


来自Builtins上的GCC文档

如果控制流到达的位置,则__builtin_unreachable该程序未定义。在编译器无法推断代码无法到达的情况下,此功能很有用。[..]

  • 为什么不直接调用`std::abort()`? (2认同)

Ayx*_*xan 6

作为一个完全便携式的解决方案,请考虑:

[[ noreturn ]] void unreachable(std::string_view msg = "<No Message>") {
    std::cerr << "Unreachable code reached. Message: " << msg << std::endl;
    std::abort();
}
Run Code Online (Sandbox Code Playgroud)

当然,消息部分是可选的。

  • @nada [`std::cerr`](https://en.cppreference.com/w/cpp/io/cerr) 应在每次操作后自动刷新。 (4认同)

Fre*_*abe 5

我喜欢用

assert(!"This should never happen.");
Run Code Online (Sandbox Code Playgroud)

...也可以与条件一起使用,如

assert(!vector.empty() || !"Cannot take element from empty container." );
Run Code Online (Sandbox Code Playgroud)

这样做的好处是,如果断言不成立,该字符串会显示在错误消息中。