首页 > 解决方案 > 如何确保某些代码被优化掉?

问题描述

tl;dr:是否可以以某种方式(例如通过编写单元测试)确保某些东西被优化掉,例如整个循环?

确保生产构建中不包含某些内容的常用方法是用#if...#endif. 但我更喜欢继续使用 C++ 机制。即使在那里,我喜欢保持简单的实现而不是复杂的模板专业化,并争辩说“嘿,编译器无论如何都会优化它”。

上下文是汽车中的嵌入式软件(二进制大小很重要),编译器通常很差。它们在安全方面经过认证,但通常在优化方面并不出色。

示例 1:在容器中,元素的销毁通常是一个循环:

for(size_t i = 0; i<elements; i++)
    buffer[i].~T();

这也适用于内置类型,例如int,因为标准允许显式调用析构函数也适用于任何标量类型 (C++11 12.4-15)。在这种情况下,循环什么都不做并且被优化了。在 GCC 中是这样,但在另一个(Aurix)中不是,我在反汇编中看到了一个字面上的空循环!所以这需要一个模板专业化来修复它。

示例 2:仅用于调试、分析或故障注入等的代码:

constexpr bool isDebugging = false; // somehow a global flag
void foo(int arg) {
    if( isDebugging ) {
        // Albeit 'dead' section, it may not appear in production binary!
        // (size, security, safety...)
        // 'if constexpr..' not an option (C++11)
        std::cout << "Arg was " << arg << std::endl;
    }
    // normal code here...
}

我可以看看拆解,当然。但作为上游平台软件,很难控制所有可能使用的目标、编译器及其选项。由于任何原因,下游项目存在代码膨胀或性能问题,这种担忧很大。

底线:是否有可能以某种方式编写软件,即已知某些代码会以一种安全的方式被优化掉#if?或者一个单元测试,如果优化不符合预期,它会失败?

[第一个问题我想到了时序测试,但是作为裸机我还没有方便的工具。]

标签: c++unit-testingc++11compiler-optimization

解决方案


if constexpr是此类测试的规范 C++ 表达式(自 C++17 起)。

constexpr bool DEBUG = /*...*/;

int main() {
    if constexpr(DEBUG) {
        std::cerr << "We are in debugging mode!" << std::endl;
    }
}

如果DEBUG为 false,则打印到控制台的代码根本不会生成。因此,如果您有诸如检查代码行为所需的日志语句之类的东西,但您不想在生产代码中与之交互,则可以将它们隐藏在if constexpr表达式中,以便在代码移动到后完全消除代码生产。


推荐阅读