3

I'm editing this question to make it more readable and less contrived. I've managed to replicate my issue with the following short piece of code. The question, then, is: why does this crash on an assertion failure with _BLOCK_TYPE_IS_VALID(pHead->nBlockUse) on the "delete p" line in ~A()?

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;
}
neuviemeporte
  • 6,310
  • 10
  • 49
  • 78
  • As per @James Kanze's suggestion, adding an empty virtual destructor for class I solved the problem in relation to this example. – neuviemeporte Feb 28 '12 at 10:13

3 Answers3

3

Haven't read the entire Question but first off Destructor in Sequence class should be marked virtual.

virtual ~Sequence();

If destructor of your polymorphic Base class is not virtual then you have a Undefined Behavior looming when deleting a derived class object through Base class pointer.

Alok Save
  • 202,538
  • 53
  • 430
  • 533
  • Sorry for the long question, but I wrote that changing the base destructor to virtual was one of the things I tried to remedy the situation and it still crashes. :( – neuviemeporte Feb 28 '12 at 08:18
3

Is the destructor of SeqItem virtual? If not, you have undefined behavior; in practice, this undefined behavior will only display immediate disasterous results if multiple inheritance is involved, and even then, not necessarily unless the inheritance is virtual. (Without multiple inheritance, it will typically seem to work, although it will often leak memory.)

James Kanze
  • 150,581
  • 18
  • 184
  • 329
  • No, SeqItem only has a single int as a member, so I didn't make a destructor for it. Actually, none of the classes in the SeqItem hierarchy have them, since they only store regular members like ints and strings. – neuviemeporte Feb 28 '12 at 09:25
  • 1
    If you delete an object, either the static type and the dynamic type must be identical, or the object type must have a virtual destructor (even if this destructor doesn't do anything). If you're deleting through a `SeqItem*`, and the actual type of the object is some derived class, `SeqItem` must have a virtual destructor, or the behavior is undefined. – James Kanze Feb 28 '12 at 09:44
  • I had absolutely no idea, I never would've thought an empty destructor would've made a diferrence. Anyway, this was spot on, thanks! – neuviemeporte Feb 28 '12 at 10:06
0

you need to derive from base class virtually - that is

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

and then

class SeqItemD : public SeqItemB, public SeqItemC { .. }
ersran9
  • 968
  • 1
  • 8
  • 13