3

匿名共用体を使用してQVariant呼び出されるようなクラスを実装しています。Variant

class Variant
{
public:
    // …

    ~Variant();

    // …

private:
    Type _type;
    union
    {
        int      _int;
        uint64_t _uint64;
        float    _float;
        void*    _ptr;
    };
};

次のようにメンバーVariant::~Variant()を削除しようとすると、セグメンテーション違反が発生します。Variant::_ptrString*

Variant::~Variant()
{
    if (_type == Type::String)
        delete reinterpret_cast<String*>(_ptr);
    else if (_type == Type::Date)
        delete reinterpret_cast<Date*>(_ptr);
    // …
}

これは次のように割り当てられます。

Variant::Variant(const String& str)
  : _type(Type::String),
    _ptr(new String(str))
{}

興味深いのは、GDB のデストラクタ スタック フレームで、ユニオン メンバーにはアクセスできないが、Variant::_typeメンバーにはアクセスできることです。

(gdb) frame
#0  0x0000000000527700 in Variant::~Variant (this=0x7fffec0337a0, __in_chrg=<optimized out>) at Sources/Types/Variant.cpp:85
85                      delete reinterpret_cast<String*>(_ptr);
(gdb) p _ptr
No symbol "_ptr" in current context.
(gdb) p _int
No symbol "_int" in current context.
(gdb) p _float
No symbol "_float" in current context.
(gdb) p _type
$2 = Variant::String

ユニオンは既に削除されているようで、_ptrアクセスできないものを削除しようとして segfautl します。しかし、なぜ?

4

1 に答える 1

3

私の精神的なデバッグ能力は、あなたが独自のコピー コンストラクターを実装しておらず、デフォルトのコンストラクターが新しいメモリを割り当てる代わりにポインターをコピーするだけであることを示しています。次に、オリジナルのコピーが破棄されると、二重削除になります。

ただし、これが単に使用する演習でない限り、boost::variantまたはboost::any既に堅牢で十分に開発されたソリューションであるためです。

于 2013-06-10T12:44:23.823 に答える