我通过C ++包装器使用C代码,
特别是我用union
包装boost::variant
,
问题是在特定情况下clang静态分析器报告“分配的值是垃圾或未定义的”-boost :: variant已使用类型int
创建(通过“ take branch true”描述的clang静态分析器),从未修改,但随后可以通过clang静态分析器分析boost::variant
,desctructor可以调用非int
类型的析构函数。
这是我的代码:
#include <boost/variant.hpp>
#include <cstdint>
#include <iostream>
#include <string>
extern "C" {
struct CFooString {
const char *data;
uintptr_t len;
uintptr_t capacity;
};
void cfoo_string_free(struct CFooString str);
struct CResultObjectString {
uint8_t is_ok;
union {
int ok;
struct CFooString err;
} data;
};
struct CResultObjectString c_func(int);
}
class MyString final : private CFooString {
public:
explicit MyString(const CFooString &o) noexcept {
data = o.data;
len = o.len;
capacity = o.capacity;
}
MyString() = delete;
MyString(const MyString &) = delete;
MyString &operator=(const MyString &) = delete;
MyString(MyString &&o) noexcept {
data = o.data;
len = o.len;
capacity = o.capacity;
reset(o);
}
MyString &operator=(MyString &&o) noexcept {
free_mem();
data = o.data;
len = o.len;
capacity = o.capacity;
reset(o);
return *this;
}
~MyString() noexcept { free_mem(); }
std::string to_std_string() const { return std::string(data, len); }
size_t size() const noexcept { return this->len; }
bool empty() const noexcept { return this->len == 0; }
private:
void free_mem() noexcept {
if (data != nullptr) {
cfoo_string_free(*this);
reset(*this);
}
}
static void reset(MyString &o) noexcept {
o.data = nullptr;
o.len = 0;
o.capacity = 0;
}
};
boost::variant<int, MyString> f1() {
CResultObjectString ret = c_func(17);
return ret.is_ok != 0 ? boost::variant<int, MyString>{ret.data.ok}
: boost::variant<int, MyString>{MyString{ret.data.err}};
}
int main() {
auto ret = f1();
if (boost::get<int>(&ret) != nullptr) {
int p = boost::get<int>(std::move(ret));
std::cout << "we get : " << p;
} else {
auto err = boost::get<MyString>(std::move(ret));
std::cout << err.to_std_string();
}
}
扫描构建g ++ -std = c ++ 11 -pedantic -Wall -Wextra -c test.cpp报告:
scan-build g++ -std=c++11 -pedantic -Wall -Wextra -c test.cpp
scan-build: Using '/usr/bin/clang-7' for static analysis
test.cpp:39:9: warning: Assigned value is garbage or undefined
len = o.len;
^ ~~~~~
test.cpp:61:7: warning: Passed-by-value struct argument contains uninitialized data (e.g., field: 'len')
cfoo_string_free(*this);
^~~~~~~~~~~~~~~~~~~~~~~
如果阅读了clang静态分析器说明,它认为
创建boost::variant<int, MyString>{ret.data.ok}
之后
可能会调用MyString::~MyString
。
我的代码或boost::variant
或clang static analyzer
出问题了吗?