Я сталкивался со случаем, когда безопасный с точки зрения типов c ++ производит несоответствующие ctor / dtors.
Следующий код генерирует два конструктора для A. Конструктор по умолчанию также создает свою базу (B), но сгенерированный по умолчанию ctor копирования / перемещения не создает B. Позднее он уничтожает B, поэтому мы получаем несоответствующие ctor / dtor.
Я пробовал это с gcc и clang и оба провалились. На форуме об ошибках gcc они предположили, что это не проблема gcc.
Возможно, я что-то упускаю, но разве нет ничего странного, когда код, безопасный для типов, приводит к вызову dtor для класса, который еще не был создан?
B() -> INSERT: 0x7fff55398b2f
~B() -> ERASE: 0x7fff55398b2f
~B() -> ERASE: 0x7fff55398b40 // <- unmatched dtor call
Assertion failed: (!all.empty()), function ~B, file gcc_bug.c, line 20.
Код следует:
#include <set>
#include <iostream>
#include <cstdint>
#include <cassert>
#include <experimental/optional>std::set<std::uintptr_t> all;
struct B
{
B()
{
std::cerr << "B() -> INSERT: " << this << "\n";
all.insert((std::uintptr_t)this);
}
~B()
{
std::cerr << "~B() -> ERASE: " << this << "\n";
assert(!all.empty()); // FAILS
assert(all.find((std::uintptr_t)this) != all.end()); // FAILS
all.erase((std::uintptr_t)this);
}
};
struct A : B {};
static std::experimental::optional<A> f()
{
A a;
return a;
}
int main()
{
auto a = f();
return 0;
}
У тебя есть B
создается неявно определенным конструктором копирования. Это, конечно, не зовет B::B()
, Если вы добавите следующий конструктор:
B(const B& other) : B()
{
*this = other;
}
вы увидите вывод:
B() -> INSERT: 0x7ffe57ef918f
B() -> INSERT: 0x7ffe57ef91b0
~B() -> ERASE: 0x7ffe57ef918f
~B() -> ERASE: 0x7ffe57ef91b0
Важный момент, который нужно убрать, это: каждый Конструктор полностью конструирует объект. По умолчанию конструктор копирования не будет вызывать конструктор по умолчанию (и, очевидно, наоборот). Поэтому, если у вас есть что-то, что нужно сделать в каждом конструкторе, вы должны явно сделать это в каждом конструкторе, либо прямым вызовом, либо цепочкой конструктора.
Других решений пока нет …