Почему при удалении объектов, участвующих в множественном (виртуальном) наследовании, происходит сбой недопустимого блока? - PullRequest
3 голосов
/ 28 февраля 2012

Я редактирую этот вопрос, чтобы сделать его более читабельным и менее надуманным.Мне удалось воспроизвести мою проблему с помощью следующего короткого фрагмента кода.Тогда возникает вопрос: почему происходит сбой при ошибке подтверждения с _BLOCK_TYPE_IS_VALID (pHead-> nBlockUse) в строке «delete p» в ~ 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;
}

Ответы [ 3 ]

3 голосов
/ 28 февраля 2012

Является ли деструктор SeqItem виртуальным? Если нет, у вас есть неопределенное поведение; на практике это неопределенное поведение будет отображать немедленные катастрофические результаты, только если задействовано множественное наследование, и даже тогда, необязательно, если наследование не является виртуальным. (Без множественного наследования это, как правило, работает, хотя часто приводит к утечке памяти.)

3 голосов
/ 28 февраля 2012

Не прочитал весь Вопрос, но сначала Разрушитель в классе Sequence должен быть помечен virtual.

virtual ~Sequence();

Если деструктором вашего полиморфного Базового класса не является virtual, то при удалении объекта производного класса с помощью указателя Базового класса вы получаете маячение Неопределенное поведение.

0 голосов
/ 28 февраля 2012

вам нужно получить из базового класса виртуально - то есть

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

, а затем

class SeqItemD : public SeqItemB, public SeqItemC { .. }
...