我想使用 UBSAN(未定义的行为消毒剂),但发现它完全没有价值,因为它会报告许多误报。
例如,一个简单std::make_shared<int>(42);
的就足以触发警告,例如
地址 0x00000236de70 内的成员访问,它不指向“_Sp_counted_base”类型的对象
将此示例简化为 MWE 表明问题在基类和继承方面更为普遍:
例子:
struct Foo{
int f(){ return g(); }
virtual int g() = 0;
};
struct Bar: Foo{
int g(){ return 42; }
};
int main(){
auto f = new Bar();
return f->g();
}
编译-fsanitize=undefined
并观看
example.cpp:15:16:运行时错误:对地址 0x000000726e70 的成员调用,它不指向“Bar”类型的对象
0x000000726e70:注意:对象的 vptr 无效
请参阅https://godbolt.org/z/0UiVtu。
连这些简单的案件都处理不好怎么办?我错过了什么吗?我应该如何正确使用 UBSAN 来检查我的代码?(这需要[几乎]没有误报)
编辑:似乎 MWE 仅适用于 Godbolt,原始代码如下所示:
#include <boost/iostreams/device/mapped_file.hpp>
#include <boost/iostreams/stream.hpp>
using MMStream = boost::iostreams::stream<boost::iostreams::mapped_file_source>;
int main(){
MMStream stream;
stream.open("a.out");
return !stream;
}
编译clang++-8 -fsanitize=undefined -fvisibility=hidden -I /opt/boost_1_64_0/include/ test.cpp /opt/boost_1_64_0/lib/libboost_iostreams.so
并运行会导致错误,例如
运行时错误:对地址 0x00000126ef30 的成员调用,它不指向“boost::detail::sp_counted_base”类型的对象