Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 09.04.2009, 16:38   #1
Scogan
 
Регистрация: 09.04.2009
Сообщений: 4
По умолчанию Полиморфизм и выделение (освобождение) памяти

Пишу код типа:

В h-файле:

Код:
class A
{
public:
    double* element;
    A();
    ~A();

    virtual func() = 0;
};

class B : public A
{
public:
    B();
    func();
};
в cpp-файле:

Код:
A::A()
{
    element = new double;
}

A::~A()
{
    delete element;
}

B::func()
{
    // whatever...
}

В прикладном файле-клиенте на стеке порождается ряд объектов типа B. При первом вызове деструктора ~A() операция delete выполняется нормально, а следующий вызов приводит к Access Violation, т.к. delete обращается к уже удаленной при первом вызове переменной element.

Собственно вопрос: в чем причина ошибки? Ведь вызов конструктора базового класса происходит опросредованно через вызов конструктора производного класса B(), значит, по идее, и деструктор должен вызываться для соответствующего объекта. При попытке перенести new и delete для element в соответственно конструктор и деструктор производного класса, оставив объявление в базовом, имею аналогичную картину.

Последний раз редактировалось MaTBeu; 09.04.2009 в 19:21.
Scogan вне форума Ответить с цитированием
Старый 09.04.2009, 17:40   #2
pu4koff
Старожил
 
Аватар для pu4koff
 
Регистрация: 22.05.2007
Сообщений: 9,065
По умолчанию

Цитата:
Сообщение от Scogan Посмотреть сообщение
В прикладном файле-клиенте на стеке порождается ряд объектов типа B. При первом вызове деструктора ~A() операция delete выполняется нормально, а следующий вызов приводит к Access Violation, т.к. delete обращается к уже удаленной при первом вызове переменной element.
Зачем удалять уже удалённое?
Цитата:
Сообщение от Scogan Посмотреть сообщение
Собственно вопрос: в чем причина ошибки? Ведь вызов конструктора базового класса происходит опросредованно через вызов конструктора производного класса B(), значит, по идее, и деструктор должен вызываться для соответствующего объекта.
Если написать как-то так:
Код:
class A
{
public:
  A();
  ~A(); // деструктор не виртуальный
}
class B: public A
...

B *b = new B;
A* a = b;
delete a;
тут вызовется только деструктор класса A, т.к. деструктор не виртуальный
pu4koff вне форума Ответить с цитированием
Старый 09.04.2009, 22:09   #3
Scogan
 
Регистрация: 09.04.2009
Сообщений: 4
По умолчанию

Цитата:
Сообщение от pu4koff Посмотреть сообщение
Зачем удалять уже удалённое?
Как это удаленное? С какой стати? Разве вызов деструктора освобождает динамическую память? Можно источник (гиперссылка тоже годится)?
Scogan вне форума Ответить с цитированием
Старый 09.04.2009, 22:18   #4
pu4koff
Старожил
 
Аватар для pu4koff
 
Регистрация: 22.05.2007
Сообщений: 9,065
По умолчанию

Цитата:
Сообщение от Scogan Посмотреть сообщение
При первом вызове деструктора ~A() операция delete выполняется нормально, а следующий вызов приводит к Access Violation, т.к. delete обращается к уже удаленной при первом вызове переменной element.
Разве не Ваши слова, что удаляется второй раз одно и то же? Код в студию как именно создаёте объект, как именно удаляете, а то мало ли что там у Вас и как происходит...
pu4koff вне форума Ответить с цитированием
Старый 09.04.2009, 22:35   #5
Scogan
 
Регистрация: 09.04.2009
Сообщений: 4
По умолчанию

Цитата:
Сообщение от pu4koff Посмотреть сообщение
Разве не Ваши слова, что удаляется второй раз одно и то же? Код в студию как именно создаёте объект, как именно удаляете, а то мало ли что там у Вас и как происходит...
Под рукой не имею, какую-либо новизну к тому, что объекты порождаются на стеке, это вряд ли добавит. В debuggere видно, что при конструировании каждого последующего объекта производного класса память в конструкторе базового класса выделяется по разным адресам. Почему же тогда в момент удаления объекта производного класса при вызове деструктора базового класса производится попытка освободить уже освобожденную память?
Scogan вне форума Ответить с цитированием
Старый 10.04.2009, 00:54   #6
Bogus Jr.
Новичок
Джуниор
 
Регистрация: 30.03.2009
Сообщений: 1
По умолчанию

насколько я помню, если в базовом классе есть виртуальные функции то и диструктор у базового класса должен быть виртуальным...

Последний раз редактировалось Bogus Jr.; 10.04.2009 в 01:15.
Bogus Jr. вне форума Ответить с цитированием
Старый 11.04.2009, 04:00   #7
zeleno
Новичок
Джуниор
 
Регистрация: 07.04.2009
Сообщений: 2
По умолчанию

Цитата:
Сообщение от Bogus Jr. Посмотреть сообщение
насколько я помню, если в базовом классе есть виртуальные функции то и диструктор у базового класса должен быть виртуальным...
Кто нибудь подтвердите это или опровергните, а то интересно)
С объяснением, пожалуйста)
zeleno вне форума Ответить с цитированием
Старый 11.04.2009, 04:59   #8
Pashan
Пользователь
 
Регистрация: 18.03.2009
Сообщений: 89
По умолчанию

Цитата:
диструктор у базового класса должен быть виртуальным...
Деструктор сам по себе никому ничего не должен. Он может быть виртуальным, а может и нет. Просто если взять код типа:

Код:
// B наследуется от A
A* ab = new B();
delete ab;
то если деструктор виртуальный, вызовется сначала деструктор B, а затем - деструктор A. Если не виртуальный - то будет вызван только деструктор A.

Scogan,
по поводу основного вопроса - можешь привести более полный код происходящего? Наверняка там какая-нибудь путаница, которую на словах фиг поймешь.
Pashan вне форума Ответить с цитированием
Старый 11.04.2009, 11:25   #9
pu4koff
Старожил
 
Аватар для pu4koff
 
Регистрация: 22.05.2007
Сообщений: 9,065
По умолчанию

Может там конструктор копирования вызывается неявно. Явно конструктор не задан и потому будет поэлементное копирование и разные объекты будут указывать на один и тот же element. В общем код в студию
pu4koff вне форума Ответить с цитированием
Старый 13.04.2009, 07:57   #10
Scogan
 
Регистрация: 09.04.2009
Сообщений: 4
По умолчанию

Цитата:
Сообщение от pu4koff Посмотреть сообщение
В общем код в студию
Искренне благодарю уважаемое программерское сообщество за неподдельный интерес. Сегодня постараюсь вычленить из проекта предмет дискуссии и привести как сам код, так и прецедент его использования в деталях.
Scogan вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Освобождение памяти AlexandrSid Общие вопросы Delphi 3 02.02.2009 13:45
Освобождение Памяти в Си volotsky Помощь студентам 2 16.12.2008 22:36
До выделение памяти MAKTE Общие вопросы C/C++ 4 20.05.2008 21:34
Выделение памяти antoha.by Паскаль, Turbo Pascal, PascalABC.NET 2 29.04.2008 20:04
выделение оперативной памяти Alar Общие вопросы Delphi 0 29.10.2006 21:56