Bor*_*rph 6 c++ unit-testing dead-code compiler-optimization c++11
tl;dr:能否以某种方式确保(例如通过编写单元测试)某些东西被优化掉,例如整个循环?
确保生产版本中不包含某些内容的常用方法是将其包装为#if...#endif
. 但我更喜欢继续使用 C++ 机制。即使在那里,我也喜欢保持简单的实现,而不是复杂的模板专业化,并认为“嘿,编译器无论如何都会优化它”。
上下文是汽车中的嵌入式软件(二进制大小很重要),编译器通常很差。它们在安全意义上得到了认证,但通常在优化方面表现不佳。
示例 1:在容器中,元素的销毁通常是一个循环:
for(size_t i = 0; i<elements; i++)
buffer[i].~T();
Run Code Online (Sandbox Code Playgroud)
这也适用于内置类型,例如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...
}
Run Code Online (Sandbox Code Playgroud)
当然,我可以看一下拆解。但作为一种上游平台软件,很难控制可能使用的所有目标、编译器及其选项。人们非常担心,由于任何原因,下游项目会出现代码膨胀或性能问题。
底线:是否有可能以某种方式编写软件,即已知某些代码可以像 a 那样以安全的方式进行优化#if
?或者单元测试,如果优化未达到预期,则会失败?
[针对第一个问题,我想到了计时测试,但作为裸机,我还没有方便的工具。]
if constexpr
是用于此类测试的规范 C++ 表达式 (C++17 起)。
constexpr bool DEBUG = /*...*/;
int main() {
if constexpr(DEBUG) {
std::cerr << "We are in debugging mode!" << std::endl;
}
}
Run Code Online (Sandbox Code Playgroud)
如果DEBUG
为 false,则根本不会生成打印到控制台的代码。因此,如果您有检查代码行为所需的日志语句之类的内容,但您不想在生产代码中与之交互,则可以将它们隐藏在if constexpr
表达式内,以便在代码移至生产。
可能有一种更优雅的方法,它不是单元测试,但如果您只是寻找特定的字符串,并且可以使其唯一,
strings $COMPILED_BINARY | grep "Arg was"
Run Code Online (Sandbox Code Playgroud)
应该显示该字符串是否被包含在内
归档时间: |
|
查看次数: |
1269 次 |
最近记录: |