优化、断言和发布模式

Optimization, asserts and release mode

本文关键字:模式 布模式 断言 优化      更新时间:2023-10-16

考虑一个函数

void f() {
   assert(condition);
   ...
}

在调试模式下,启用断言,编译器可以自由地假设condition保持,因为如果它不保持,其余的代码将不会被执行。

但是,在发布模式下,我相信编译器只会看到
void f() {
   ...
}

,不能再假设condition

是否有任何编译器指令或静态断言技巧,让编译器知道某些不变量?

这不能在可移植的C或c++中完成。

一些编译器提供了内部函数,如__assume(用于MSVC)和__builtin_unreachable(用于GCC, ICC和Clang),可用于此目的。

例如:

void f() {
    __assume(condition); //For MSVC
    /*...*/
}
void f() {
    if (!condition) __builtin_unreachable(); //for GCC and Clang
    /*...*/
}

动词"假设"的一部分,这使得问题有点晦涩,(并使我担心你对编译器真正做什么有一个真正的理解)assert是一个宏,当NDEBUG被定义时(通常在发布版本中),并且-当在调试构建中使用时-抛出错误,如果条件不为真。

这里的要点是,只有当条件总是为真时,程序才是"正确的"。在你证明了它(在测试构建中)之后,即使在发布代码中也没有必要继续证明它。

更微妙的问题可能是如果"condition"本身有一个你不想在发布版本中删除的副作用。

在这种情况下,只需将"condition"从断言中取出,将结果存储在bool中并在bool上进行断言,如

bool condition_fine = (condition);
assert(condition_fine);

这允许在任何情况下对条件进行评估,但是从发布版本中删除错误检查。