утечка памяти при удалении производного класса с указателем базового класса - PullRequest
4 голосов
/ 04 марта 2011

У меня проблема с утечкой памяти. У меня есть указатель базового класса. Исходя из этого, я использую new для выделения различных производных классов. Затем, когда я пытаюсь delete эти классы со ссылкой (не Typecasted), я получаю утечку памяти. Я исследовал проблему и обнаружил, что должен добавить виртуальный деструктор в базовый класс, но я попробовал это, и у меня все еще есть утечка памяти; то есть, согласно моему диспетчеру задач, использование памяти продолжает расти с каждым выделением и удалением производного класса с использованием указателя базового класса. Я попытался сделать его абстрактным деструктором и добавил деструкторы к производным классам, но я получил неопределенную ошибку ссылки. Я также пытался типизировать указатель как указатель производного класса для delete, но, очевидно, это приводит к сбою программы.

Кто-нибудь знает, что мне делать?

Пример кода:

class A {
public:
  A();
  ~A() {};
  virtual ~A();      /*or*/
  virtual ~A()=0;    /*or*/
                     /*or nothing?*/
}

class B: private A {
public:
  B();
  ~B() {};           /*this?*/
                     /*or nothing?*/
}

Ответы [ 4 ]

5 голосов
/ 04 марта 2011

Насколько вы уверены, что действительно есть утечка памяти? Как правило, диспетчер задач здесь не сильно поможет, так как он не может сказать, сколько памяти, принадлежащей вашему процессу, фактически выделено. Даже освобожденная память по-прежнему принадлежит вашему процессу и может быть использована позднее для управления памятью (обычно это malloc-подобная системная библиотека).

Используйте инструмент, такой как mallocdebug, valgrind, cleany и т. Д., Чтобы узнать, действительно ли существует утечка памяти. Эти инструменты заменят реализацию malloc новой, которая отслеживает выделенную память и сообщает о памяти, которая не освобождается после завершения процесса.

Примечание. В большинстве систем память, освобожденная от процесса, не возвращается в систему до завершения процесса. Тем не менее, он доступен для новых распределений в рамках того же процесса.

3 голосов
/ 04 марта 2011

использование virtual ~A();

Я бы удивился, если бы virtual ~A()=0 было разрешено.

С этим кодом:

A* base = new B();
delete base;

деструктор для B, тогда будет называться A.

Если у вас все еще есть утечка памяти, значит, у вас есть еще одна утечка в другом месте.

3 голосов
/ 04 марта 2011

Если у вас есть виртуальный деструктор, будет вызван деструктор (ы) вашего подкласса (ов). не нужно делать никакой эзотерической магии с абстрактными деконструкторами или чем-то еще.

Я бы предположил, что утечка памяти находится где-то внутри вашего объекта. Может быть, вы вызываете new() для чего-то в конструкторе B (или A?), Но вы не удаляете это. Не видя больше кода, все, что я могу сказать, это "ваша установка деструктора в порядке".

0 голосов
/ 04 марта 2011

Вы можете использовать:

virtual ~A(){}

или

virtual ~A()=0; 

// as long as there is also:
A::~A(){}  // inline in the header file or non-inline in the cpp file.

Это означает, что:

A* base;
...
delete base;

вызовет все деструкторы производных классов в правильном порядке.

Обратите внимание, что чистый виртуальный деструктор: virtual ~A()=0; может быть полезен, если вам нужен абстрактный базовый класс, когда никакие другие функции-члены не являются чисто виртуальными.

...