Jos*_*ica 6 c++ constructor clang clang-static-analyzer
考虑这个 C++ 代码:
struct SomeStruct {
SomeStruct() noexcept;
};
//SomeStruct::SomeStruct() noexcept {}
class SomeClass {
const bool b;
const SomeStruct s;
public:
SomeClass() : b(true) {}
operator bool() const { return b; }
};
void f() {
int *p = new int;
if (SomeClass())
delete p;
}
Run Code Online (Sandbox Code Playgroud)
当我运行clang --analyze -Xanalyzer -analyzer-output=text它时,我得到这个:
q72007867.cpp:20:1: warning: Potential leak of memory pointed to by 'p' [cplusplus.NewDeleteLeaks]
}
^
q72007867.cpp:17:12: note: Memory is allocated
int *p = new int;
^~~~~~~
q72007867.cpp:18:7: note: Assuming the condition is false
if (SomeClass())
^~~~~~~~~~~
q72007867.cpp:18:3: note: Taking false branch
if (SomeClass())
^
q72007867.cpp:20:1: note: Potential leak of memory pointed to by 'p'
}
^
1 warning generated.
Run Code Online (Sandbox Code Playgroud)
不过,取消注释 的构造函数的定义SomeStruct会使警告消失。const bool b;交换和的顺序const SomeStruct s;也会使其消失。在原始程序中,实际上是否存在 的构造函数的其他定义SomeStruct会导致在那里采取错误分支,或者这是 Clang 静态分析器中的误报?
没有标准兼容的方法可以const在初始化后更改成员;任何机制都将是UB。
喜欢
struct foo{
const bool b=true;
foo(){ b=false; }
};
Run Code Online (Sandbox Code Playgroud)
是非法的,编辑它的代码也是const_cast非法的:b
struct foo{
const bool b=true;
foo(){ const_cast<bool&>(b)=false; }
};
Run Code Online (Sandbox Code Playgroud)
(第二个版本可以编译,但会生成 UB)。
遗憾的是,这样的 UB 并不罕见。例如,我可以实现 的构造函数来在指针地址SomeStruct之前修改内存this。这将是双重非法的(const在构造后修改值,并违反可达性规则),但根据优化设置,它可以工作。
另一方面,编译器可以自由地注意到唯一的构造函数分配true给b然后转换operator bool为仅 return true。
b但相反,一旦发生对可见源代码之外的函数体的调用,静态代码分析器就会放弃验证状态。放弃这是一件非常合理的事情。在这里,该函数甚至获取指向同一个临时对象的指针;做一个完整的证明,无论运行什么代码,指针都不能改变某些状态是可能的,但不这样做似乎也是合理的。
就风格而言,代码也有点混乱。一个可证明为真的分支要么不应该存在,要么失败的分支在语义上应该有意义。两者都没有发生在这里;任何阅读此代码的人都无法从代码结构确定正确性;代码结构看起来有误导性。
| 归档时间: |
|
| 查看次数: |
213 次 |
| 最近记录: |