简体   繁体   English

删除对象时出现C ++断言错误

[英]C++ assertion error while deleting object

I have strange assertion error and I can not find what is wrong with this code. 我有一个奇怪的断言错误,我找不到此代码有什么问题。

Assertion expression is _BLOCK_TYPE_IS_VALID(pHead->nBlockUse). 断言表达式为_BLOCK_TYPE_IS_VALID(pHead-> nBlockUse)。

I simplified code a bit for better readability. 我对代码进行了简化,以提高可读性。

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

The idea is that an object witch inherits Creator, can create any other object, and hold pointers to those objects. 这个想法是,一个对象巫婆继承了Creator,可以创建任何其他对象,并保留指向这些对象的指针。 While programmer can work with references. 虽然程序员可以使用引用。 And when "super" object is destroyed, all "sub" objects are destroyed too. 当“超级”对象被破坏时,所有“子”对象也被破坏。

Program works like a charm if I change to: 如果我更改为以下程序,程序将像一个魅力一样工作:

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();
}

Now create method creates only one type of object ( object A in this example ). 现在,create方法仅创建一种类型的对象(在此示例中为对象A)。 But I need, that create method could create any object that inherits MyObject. 但是我需要,该create方法可以创建任何继承MyObject的对象。 Like in first peace of code. 就像在第一个代码和平中一样。

Any help for this assertion error would be appreciated. 对于此断言错误的任何帮助将不胜感激。 Thanks. 谢谢。

The issue is that your MyObject class lacks a virtual destructor, and you're attempting to call delete on a pointer to the derived class using a pointer to the base class MyObject . 问题在于您的MyObject类缺少虚拟析构函数,并且您试图使用指向基类MyObject的指针来调用指向派生类的指针的delete Issuing a delete on a derived object through a base class pointer is undefined behavior if the base class destructor is not virtual. 如果基类析构函数不是虚拟的,则通过基类指针对派生对象进行delete是未定义的行为。

5.3.5 Delete (Paragraph 3) 5.3.5删除(第3款)

In the first alternative (delete object), if the static type of the operand is different from its dynamic type, the static type shall be a base class of the operand's dynamic type and the static type shall have a virtual destructor or the behavior is undefined . 在第一个替代方案(删除对象)中,如果操作数的静态类型不同于其动态类型,则静态类型应为操作数动态类型的基类, 并且静态类型应具有虚拟析构函数或行为未定义

Once the destructor is made virtual in the base class MyClass , the following works correctly in Visual Studio 2013: 将析构函数在基类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>();
} 

I think the issue is with multiple inheritance. 我认为问题在于多重继承。 Here's a simplified way to reproduce the problem. 这是重现该问题的简化方法。 It can be fixed by 可以通过固定

  • casting it to the most derived type OR 将其转换为最派生类型OR
  • having the destructor of the base class be virtual. 使基类的析构函数是虚拟的。

In your case, the virtual function approach is best as it is recommended to have base class destructor(s) to be virtual to get the destruction calls through the inheritance hierarchy. 在您的情况下,最好使用虚拟函数方法,因为建议将基类析构函数虚拟化,以通过继承层次结构获取销毁调用。

class A 
{
};

class B
{
};

class C : public A, public B
{
};

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

To fix it 要解决这个问题

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

The second program works because it is similar to this below. 第二个程序可以正常工作,因为它与下面的类似。

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

Problem is that you try to delete A object via MyObject pointer and MyObject destructor is not virtual. 问题是您尝试通过MyObject指针删除一个对象,而MyObject析构函数不是虚拟的。 You could make MyObject's destructor virtual and then you can delete subclasses objects via pointer to MyObject. 您可以将MyObject的析构函数设为虚拟,然后可以通过指向MyObject的指针删除子类对象。 For more details on this issue see this question 有关此问题的更多详细信息,请参阅问题

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM