【发布时间】:2021-01-11 21:43:39
【问题描述】:
这个简化的示例代码在静态分析下引发 C6001:
struct st_facade
{
st_facade &operator=(const int new_value) { m_value = new_value; return *this;}
private:
int m_value;
};
struct foo
{
st_facade my_int;
};
void main()
{
foo f;
f.my_int= 0; // C6001: Using uninitialized memory 'f'.
}
我的理解是,之所以会引发此警告,是因为假设重载的赋值运算符可能正在读取未初始化的内存。但在这种情况下,我们并没有这样做——我们实际上是在初始化内存。
如何告诉编译器这里的赋值运算符没有使用任何未初始化的内存?我尝试使用几种不同的 SAL 注释来表达这一点,但没有任何效果。
在这种情况下,零初始化内存(即使用foo f{}; 或st_facade my_int{};)不是正确的答案。在实际代码中,这样的初始化可能会产生不可接受的性能影响
[edit] 出于类似的原因,基于构造函数的初始化也不是正确的答案。我们需要这种类型在创建时未初始化;我们需要通知静态分析器赋值运算符执行初始化。
[编辑 2] 更一般地说,我们需要一种方法来告诉静态分析器“此方法初始化对象”,而无需实现构造函数或对类型的每个实例进行零初始化。
【问题讨论】:
-
re:“可能正在读取未初始化的内存”:也许某些类可能会根据第三个字段的值将传入值存储在两个不同字段之一中。在这种情况下,分析将正确识别出我们在读取第三个字段时正在访问未初始化的内存。 (尽管编译器无法在不执行比当前能力更全面的分析的情况下具体指向第三个字段)
-
也许有一个(非显式)构造函数
st_facade(int)并将其改为移动赋值st_facade& operator=(st_facade&&) noexcept = default?
标签: c++ static-analysis sal