[英]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>();
}
我認為問題在於多重繼承。 這是重現該問題的簡化方法。 可以通過固定
在您的情況下,最好使用虛擬函數方法,因為建議將基類析構函數虛擬化,以通過繼承層次結構獲取銷毀調用。
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.