簡體   English   中英

刪除對象時出現C ++斷言錯誤

[英]C++ assertion error while deleting object

我有一個奇怪的斷言錯誤,我找不到此代碼有什么問題。

斷言表達式為_BLOCK_TYPE_IS_VALID(pHead-> nBlockUse)。

我對代碼進行了簡化,以提高可讀性。

class Creator
{
public:
    virtual ~Creator()
    {
        for (MyObject* item : _list)
        {
            delete item; <-- assertion error here
            item = 0;
        }
        _list.clear();
    }

    template <class T>
    T& create()
    {
        T * item = new T();
        _list.push_back(item);
        return *item;
    }

private:
    std::list<MyObject*> _list;
};

class A : public MyObject, public Creator
{
};

class B : public MyObject, public Creator
{
};

int main()
{
    A a;
    a.create<A>();
} <-- call of destructor

這個想法是,一個對象巫婆繼承了Creator,可以創建任何其他對象,並保留指向這些對象的指針。 雖然程序員可以使用引用。 當“超級”對象被破壞時,所有“子”對象也被破壞。

如果我更改為以下程序,程序將像一個魅力一樣工作:

template <class T>
class Creator
{
public:
    virtual ~Creator()
    {
        for (T* item : _list)
        {
            delete item;
            item = 0;
        }
        _list.clear();
    }

    T& create()
    {
        T * item = new T();
        _list.push_back(item);
        return *item;
    }

private:
    std::list<T*> _list;
};

class A : public MyObject, public Creator<A>
{
};

class B : public MyObject, public Creator<B>
{
};

int main()
{
    A a;
    a.create();
}

現在,create方法僅創建一種類型的對象(在此示例中為對象A)。 但是我需要,該create方法可以創建任何繼承MyObject的對象。 就像在第一個代碼和平中一樣。

對於此斷言錯誤的任何幫助將不勝感激。 謝謝。

問題在於您的MyObject類缺少虛擬析構函數,並且您試圖使用指向基類MyObject的指針來調用指向派生類的指針的delete 如果基類析構函數不是虛擬的,則通過基類指針對派生對象進行delete是未定義的行為。

5.3.5刪除(第3款)

在第一個替代方案(刪除對象)中,如果操作數的靜態類型不同於其動態類型,則靜態類型應為操作數動態類型的基類, 並且靜態類型應具有虛擬析構函數或行為未定義

將析構函數在基類MyClass中設置為虛擬后,以下將在Visual Studio 2013中正常工作:

#include <list>
struct MyObject 
{
    virtual ~MyObject() {}
};

class Creator
{
public:
    virtual ~Creator()
    {
        for (MyObject* item : _list)
        {
            delete item; 
            item = 0;
        }
        _list.clear();
    }

    template <class T>
    T& create()
    {
        T * item = new T();
        _list.push_back(item);
        return *item;
    }

private:
    std::list<MyObject*> _list;
};

class A : public MyObject, public Creator
{
};

class B : public MyObject, public Creator
{
};

int main()
{
    A a;
    a.create<A>();
} 

我認為問題在於多重繼承。 這是重現該問題的簡化方法。 可以通過固定

  • 將其轉換為最派生類型OR
  • 使基類的析構函數是虛擬的。

在您的情況下,最好使用虛擬函數方法,因為建議將基類析構函數虛擬化,以通過繼承層次結構獲取銷毀調用。

class A 
{
};

class B
{
};

class C : public A, public B
{
};

int main()
{
    // Fails with memory heap error
    B* pB = new C();
    delete pB;
}

要解決這個問題

int main()
{
    B* pB = new C();
    // Casting it to the "full" type will fix it
    C* pC = static_cast<C*>(pB);
    delete pC;
}

第二個程序可以正常工作,因為它與下面的類似。

int main()
{
    // Pointer to the "full" type works
    C* pC = new C();
    delete pC;
}

問題是您嘗試通過MyObject指針刪除一個對象,而MyObject析構函數不是虛擬的。 您可以將MyObject的析構函數設為虛擬,然后可以通過指向MyObject的指針刪除子類對象。 有關此問題的更多詳細信息,請參閱問題

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM