【发布时间】:2018-12-13 03:11:59
【问题描述】:
我正在试验 Clang 6.0 的 Memory Sanitizer(MSan)。 代码用
编译clang++ memsans.cpp -std=c++14 -o memsans -g -fsanitize=memory -fno-omit-frame-pointer -Weverything
在 Ubuntu 18.04 上。根据 MSan documentation
它可以容忍复制未初始化的内存,而且也很简单 逻辑和算术运算。一般来说,MemorySanitizer 静默跟踪未初始化数据在内存中的传播,以及 在采用(或不采用)代码分支时报告警告,具体取决于 在一个未初始化的值上。
所以下面的代码不会产生任何错误
#include <iostream>
class Test {
public:
int x;
};
int main() {
Test t;
std::cout << t.x;
std::cout << std::endl;
return 0;
}
但这会
#include <iostream>
class Test {
public:
int x;
};
int main() {
Test t;
if(t.x) {
std::cout << t.x;
}
std::cout << std::endl;
return 0;
}
理想情况下,人们希望这两个代码示例都产生某种错误,因为两者都“使用”了一个未初始化的变量,即第一个正在打印它。这段代码是一个小的测试代码,因此第一个代码中的错误很明显,但是如果它是一个带有类似错误的大型代码库,MSan 会完全错过这个。是否有任何 hack 可以强制 MSan 也报告此类错误?
【问题讨论】:
-
请注意,一些编译器可能会捕捉到未初始化变量的使用:GCC (godbolt.org/g/YXk4z1) 和 MSVC (godbolt.org/g/UPmBK6)。
-
我有点惊讶第一个示例没有产生错误,因为
itoa()应该需要对数据进行一些分支才能知道何时停止。 (也许这是在 libc++ 的预编译部分执行的?) -
@Acorn 使用像 MSan 这样的工具,我期待运行时调试,您的建议是正确的,但它是编译时检查。
-
好像是个bug,你可以记录一下
-
将尽可能多的工作(包括验证)预先加载到编译时是 C++ 最基本的方面之一。像 MSan 这样的工具是很好的安全网,但它们绝不应该是您发现错误的主要手段。 (我认为您的问题仍然有效,只是回复您对编译与运行时检查的看法)
标签: c++ memory clang llvm address-sanitizer