3

この質問を編集して、読みやすく、不自然さを軽減しています。次の短いコードで問題を再現できました。問題は、~A() の "delete p" 行で _BLOCK_TYPE_IS_VALID(pHead->nBlockUse) のアサーションが失敗すると、なぜこれがクラッシュするのかということです。

class A;

class I
{
public:
    I(const A *p) : parent_(p) {}

    virtual void foo() = 0;
protected:
    const A *parent_;
};

class I1 : public virtual I
{
public:
    I1(const A *p) : I(p) {}

    virtual void foo() {}
};

class A
{
public:
    A() {}
    virtual ~A()
    {
        for (size_t i = 0; i < it_.size(); ++i)
        {
            I *p = it_.at(i);
            delete p;
        }
    }

    virtual I* add() { I *p = new I1(this); it_.push_back(p); return p; }
protected:
    vector<I*> it_;
};


int _tmain(int argc, _TCHAR* argv[])
{
    A *a = new A();
    for (int i = 0; i < 10; ++i) a->add();
    delete a;

    system("pause");
    return 0;
}
4

3 に答える 3

3

SeqItem仮想のデストラクタですか?そうでない場合は、未定義の動作があります。実際には、この未定義の動作は、多重継承が含まれている場合にのみ即時の悲惨な結果を表示します。それでも、継承が仮想である場合を除き、必ずしもそうとは限りません。(多重継承がなければ、メモリがリークすることがよくありますが、通常は機能しているように見えます。)

于 2012-02-28T08:41:27.650 に答える
3

質問全体を読んでいませんが、最初にSequenceクラスのデストラクタをマークする必要がありますvirtual

virtual ~Sequence();

ポリモーフィック ベース クラスのデストラクタがそうでないvirtual場合、ベース クラス ポインタを介して派生クラス オブジェクトを削除すると、未定義の動作が迫ってきます。

于 2012-02-28T07:52:45.167 に答える
0

基本クラスから仮想的に派生する必要があります-つまり

class SeqItemB : virtual public SeqItemA { .. }
class SeqItemC : virtual public SeqItemA { .. }

その後

class SeqItemD : public SeqItemB, public SeqItemC { .. }
于 2012-02-28T08:09:21.380 に答える