问题描述
我有以下代码,我确信可以从垃圾内存中读取,但 clang 消毒剂不会抱怨。
我可以做些什么来触发它们,或者我应该将其视为限制/错误?
#include <algorithm>
#include <iostream>
#include <vector>
struct B{
int x;
};
struct D : public B{
short y;
D& operator = (const D& other) {
y = other.y;
return *this;
}
};
int main() {
D var1{4,7},var2;
var2=var1;
std::cout << var2.x << " " << var2.y << std::endl;
}
我尝试设置 O0,因为这有时会有所帮助,但这次没有。
我也愿意使用 gcc,但我认为 gcc 没有内存清理器,只有 asan。
解决方法
当堆栈或堆分配的内存被分配时,会出现未初始化的值 在写之前阅读。 MSan 检测这些值的情况 影响程序执行。
MSan 是位精确的:它可以跟踪位域中未初始化的位。它 将容忍复制未初始化的内存,以及简单的逻辑 和算术运算。一般来说,MSan 默默地 跟踪内存中未初始化数据的传播,并报告一个 当代码分支被采用(或不采用)时发出警告,具体取决于 未初始化的值。
也就是说,为了尽量减少误报,在抱怨之前,clang 会等待,直到确信未初始化的内存确实对程序执行有影响(采用不同的分支,从 main 返回不同的值等)。复制未初始化的内存可能是无害的。
在您的特定程序中,未初始化值的实际使用发生在标准库中,甚至可能只是在 C 库中,这些库尚未使用 MSan 进行检测,因此您不会收到警告。
使用 MSan 构建程序中的所有代码(包括它使用的库,特别是 C++ 标准库)至关重要。
这种限制是这种消毒剂远不如 ASan 或 UBSan 受欢迎的主要原因。
回到这个简单的程序,各种静态分析工具都可以检测到问题,甚至只有 g++ -Wall -O
会发出警告,但请注意误报并不少见。
x.cc: In function 'int main()':
x.cc:20:28: warning: 'var2.D::<anonymous>.B::x' is used uninitialized [-Wuninitialized]
20 | std::cout << var2.x << " " << var2.y << std::endl;
| ^~~~~