boost变量可以为非活动变量调用析构函数吗?

时间:2018-12-09 11:46:44

标签: c++ c++11 boost clang-static-analyzer

我通过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::variantclang static analyzer出问题了吗?

0 个答案:

没有答案