Время от времени gcc выдает предупреждение о работе с boost :: опционально с помощью возможно-неинициализированного, но я предположил, что это ложноположительный результат (как описано здесь https://github.com/boostorg/optional/issues/72).
Но теперь valgrind сообщает об этой же проблемево время выполнения, так что-то не так, любая идея, в чем проблема:
//Foo.hpp
#include <boost/optional.hpp>
#include <boost/variant.hpp>
#include <cstdio>
#include <string>
extern "C" {
typedef struct FooOpaque FooOpaque;
FooOpaque *Foo_new();
void Foo_delete(const FooOpaque *self);
}
class Foo {
public:
explicit Foo(FooOpaque *o) noexcept : self_(o) {}
Foo(const Foo &) = delete;
Foo &operator=(const Foo &) = delete;
Foo(Foo &&o) noexcept : self_(o.self_) { o.self_ = nullptr; }
Foo &operator=(Foo &&o) noexcept {
assert(this != &o);
free_mem(this->self_);
self_ = o.self_;
o.self_ = nullptr;
return *this;
}
~Foo() noexcept { free_mem(this->self_); }
private:
static void free_mem(FooOpaque *&p) noexcept {
// printf("test\n");
if (p != nullptr) {
Foo_delete(p);
}
p = nullptr;
}
FooOpaque *self_ = nullptr;
};
boost::variant<boost::optional<Foo>, std::string> f_res_opt(int var);
//Foo.cpp
#include <cassert>
#include <cstdint>
#include <cstring>
#include "Foo.hpp"
extern "C" {
struct FooOpaque {
int data;
};
FooOpaque *Foo_new() {
printf("Foo_new begin\n");
auto p = new FooOpaque;
p->data = 17;
return p;
}
void Foo_delete(const FooOpaque *self) {
assert(self != nullptr);
printf("Foo_new delete\n");
delete self;
}
}
boost::variant<boost::optional<Foo>, std::string> f_res_opt(int var) {
switch (var) {
case 0:
return {boost::optional<Foo>{Foo{Foo_new()}}};
case 1:
return {boost::optional<Foo>{boost::none}};
case 2:
return {std::string{}};
default:
std::abort();
}
}
// main.cpp
#include "Foo.hpp"
int main() {
auto res1 = f_res_opt(0);
auto res1_ok = boost::get<boost::optional<Foo>>(boost::move(res1));
printf("step 2\n");
auto res2 = f_res_opt(1);
auto res2_ok = boost::get<boost::optional<Foo>>(boost::move(res2));
printf("step 3\n");
auto res3 = f_res_opt(2);
auto res3_ok = boost::get<std::string>(boost::move(res3));
}
Valgrind и GCC сообщает о проблеме в строке:
auto res2_ok = boost::get<boost::optional<Foo>>(boost::move(res2));
, что потенциал Foo::free_mem
может использоваться для унифицированной памяти.
Странная вещь, что если я включу printf в Foo::free_mem
gcc warning (9.1.0) исчезнет и valgrind (3.15) не сообщит о каких-либо проблемах, если я это прокомментируюback gcc и valgrind сообщают о проблеме.
Я компилирую пример с gcc следующим образом:
g++ -ggdb -O3 -Wall -std=c++11 -Wextra main.cpp foo.cpp
Итак, что происходит, ошибка в моем коде, в boost :: option, илиодновременная ошибка в valgrind и g ++?
Может быть эта ошибка в g ++, которая генерирует неправильный код и поэтому valgrind также жалуется на ошибку?