Утечка памяти в C ++, кажется, усугубляется после добавления операторов удаления - PullRequest
0 голосов
/ 22 января 2011

Редактировать: Может кто-нибудь объяснить, почему добавление операторов удаления не меняет вывод Valgrind?Пожалуйста, не просите меня читать книги по C ++, я просмотрел пару и не нашел там ответов.

Я новичок в C ++, пришедший из мира Java, у меня, похоже, проблемы с пониманием того, как использовать операторы new и delete.

У меня есть метод (myMethod ()), который инициирует класс MyClass.В MyClass есть несколько массивов и несколько других объектов, создаваемых с использованием операторов new и new [].Изначально у меня не было деструктора, написанного для этого класса (я предполагал, что когда элемент управления вернется к основному из моего метода, эти объекты MyClass и все, что с ним связано, будут автоматически «освобождены»).

Когда я запустил свою программу с Valgrind, я получил сводку утечек:

==9446== LEAK SUMMARY:
==9446==    definitely lost: 1,957,019 bytes in 38 blocks.
==9446==    indirectly lost: 4,171,184 bytes in 3,040 blocks.
==9446==      possibly lost: 0 bytes in 0 blocks.
==9446==    still reachable: 91,984 bytes in 991 blocks.
==9446==         suppressed: 0 bytes in 0 blocks.
==9446== Reachable blocks (those to which a pointer was found) are not shown.
==9446== To see them, rerun with: --show-reachable=yes

Поэтому я добавил деструктор, который удаляет все массивы и устанавливает для объектов значение null.Я явно не вызываю delete для объекта MyClass.Теперь, когда я запускаю свою программу с использованием Valgrind, я получаю сводку утечек.

LEAK SUMMARY:
==9223==    definitely lost: 1,957,019 bytes in 38 blocks.
==9223==    indirectly lost: 4,171,184 bytes in 3,040 blocks.
==9223==      possibly lost: 0 bytes in 0 blocks.
==9223==    still reachable: 91,984 bytes in 991 blocks.
==9223==         suppressed: 0 bytes in 0 blocks.
==9223== Reachable blocks (those to which a pointer was found) are not shown.
==9223== To see them, rerun with: --show-reachable=yes

Когда я явно удаляю объект MyClass, количество потерянных байтов больше!

==9268== LEAK SUMMARY:
==9268==    definitely lost: 3,353,187 bytes in 1,253 blocks.
==9268==    indirectly lost: 28,376 bytes in 343 blocks.
==9268==      possibly lost: 0 bytes in 0 blocks.
==9268==    still reachable: 91,984 bytes in 991 blocks.
==9268==         suppressed: 0 bytes in 0 blocks.
==9268== Reachable blocks (those to which a pointer was found) are not shown.
==9268== To see them, rerun with: --show-reachable=yes

Я попытался переименовать деструктор в метод freeMemory () и затем вызвал freeMemory () перед выходом из myMethod () и это сводка утечек.Это выше, чем у любого из них.

== LEAK SUMMARY:
==8998==    definitely lost: 5,271,299 bytes in 1,205 blocks.
==8998==    indirectly lost: 67,264 bytes in 410 blocks.
==8998==      possibly lost: 0 bytes in 0 blocks.
==8998==    still reachable: 91,984 bytes in 991 blocks.
==8998==         suppressed: 0 bytes in 0 blocks.
==8998== Reachable blocks (those to which a pointer was found) are not shown.
==8998== To see them, rerun with: --show-reachable=yes

Наверное, мой вопрос в том, что происходит?Valgrind, кажется, указывает, что утечка в конструкторе для MyClass и в методе в MyClass.Может кто-нибудь объяснить мне, как работают операторы new и delete?Я не могу найти прозрачный ресурс в Интернете, поэтому, если кто-нибудь сможет указать мне на такой ресурс, это тоже будет здорово!

Ответы [ 2 ]

6 голосов
/ 22 января 2011

Поскольку вы пришли из Java, я должен сначала упомянуть, что чаще всего вам не нужно использовать new в C ++.

Если вам нужна переменная типа T, тогда просто объявитепеременная типа T.Вот и все.

Для вашего массива вместо указателя и new используйте std::vector, например

#include <vector>

int main()
{
    std::vector<int>  v( 10 );    // 10 elements
    v.resize( 42 );               // now 42 elements
}

. Он управляет памятью автоматически и правильно.

Что касается ошибки, с которой вы столкнулись, то это , вероятно, из-за невозможности рассмотреть все способы, которыми ваш объект может быть скопирован.Существует правило 3 (для C ++ 98), которое гласит, что если вам нужен какой-либо пользовательский деструктор, пользовательский конструктор копирования или пользовательский оператор назначения копирования, то вам, вероятно, понадобятся все три.Но опять же, вместо того, чтобы возиться с тем, что трудно понять правильно, просто используйте std::vector или какой-то другой контейнер.

А там, где вам действительно нужно управлять жизнями более непосредственно, используйте умные указатели, такие как std::auto_ptr (из стандартной библиотеки) и boost::shared_ptr (из библиотеки Boost).Это централизует сложный код управления временем жизни.С глаз долой, Just Working ™.

Приветствия и hth.

2 голосов
/ 22 января 2011

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

Обратите внимание, однако, что когда вы добавили деструкторы, вы сократили объем памятиутечка означает, что большая часть этой памяти перешла из «косвенно потерянной» в «определенно потерянную», что означает, что ваши деструкторы не очищают все.new и почти никогда new[], delete или delete[].Обычно контейнеры (такие как std::vector) и интеллектуальные указатели (такие как shared_ptr) могут использоваться для удаления всех подверженных ошибкам ручного управления памятью из приложения.

...