C++ assertion error while deleting object

不想你离开。 提交于 2019-11-28 13:21:29

问题


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).

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. 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 ). But I need, that create method could create any object that inherits MyObject. Like in first peace of code.

Any help for this assertion error would be appreciated. Thanks.


回答1:


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. Issuing a delete on a derived object through a base class pointer is undefined behavior if the base class destructor is not virtual.

5.3.5 Delete (Paragraph 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:

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



回答2:


Problem is that you try to delete A object via MyObject pointer and MyObject destructor is not virtual. You could make MyObject's destructor virtual and then you can delete subclasses objects via pointer to MyObject. For more details on this issue see this question




回答3:


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
  • 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;
}


来源:https://stackoverflow.com/questions/27768468/c-assertion-error-while-deleting-object

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!