Можно ли удалить объекты в подфункции?

0

У меня проблема с утечкой памяти в C++.

Я создаю объект (новый TYPE) и передаю его подфункции. Я знаю, что мне нужно удалить объект, чтобы избежать утечек памяти, но, когда я вызываю delete на объекте внутри подфункции, это приводит к сбою приложения:

void subfunction (TYPE* oldObject,....) {
    //deep-copy object
    TYPE* object = new TYPE(oldObject->p1,oldObject->p2,....)
    subfunction (object,....)
    delete oldObject
}

В чем проблема? Нужно ли мне удалять объект в той же самой функции, в которой он был создан?

Мне не разрешено удалять объект внутри функции, который был аргументом для этой функции?

EDIT: сообщение об ошибке " * Ошибка в"./a.out ': free(): недопустимый размер: 0x00007fff4fbe59c0 * '

Теги:
memory-leaks

5 ответов

2

В чем проблема?

Вы, вероятно, дважды удаляете один и тот же объект. Это легко сделать, когда вы бросаете указатели и надеетесь, что что-то удалит его в нужное время.

Нужно ли мне удалять объект в той же самой функции, в которой он был создан?

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

Мне не разрешено удалять объект внутри функции, который был аргументом для этой функции?

Вам разрешено; но вы не должны, так как вызывающий будет оставлен с висящим указателем. Если он пытается сделать что-либо с ним после удаления объекта, тогда могут возникнуть всевозможные ошибки.

Избегайте new если вам это действительно нужно; и использовать интеллектуальные указатели для управления всем, что вы создаете с new. Тогда вы можете продолжить писать полезный код, вместо того, чтобы отлаживать шаткую кучу памяти.

  • 0
    Я копирую объект прямо перед вызовом подфункции - поэтому каждая подфункция имеет свой собственный oldObject, который удаляется внутри. Я не вижу никаких изменений в том, что объект удаляется дважды.
  • 0
    @ user3355815: И все же, это так.
0

Я - нож для ног; к сожалению, моя система разбилась, и я не хранил trashmailaddress для входа, поэтому могу ответить теперь только как новый пользователь

фонбранд действительно дал правильный намек. Первый объект был инициализирован значениями по умолчанию как

TYPE c; TYPE* cp =&c;

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

  • 0
    Нет, только новые объекты могут быть удалены: new / delete и new [] / delete [] работают парами. для каждого нового должно быть ровно 1 удаление.
0

Несколько строк, которые вы показываете, не позволяют вообще диагностировать проблему. Как говорят другие ответы и комментарии, это, вероятно, связано с удалением объекта дважды или, возможно, с удалением объекта, который не был задан new. Или может быть, что какой-то другой код попирает ваш указатель или отклоняется за пределы выделенного объекта, и то, что, наконец, видит delete, повреждено.

В C++ есть много вещей, которые вы можете сделать, не все из них обязательно хорошие идеи. И управление памятью сложно. Вы можете оставить большую часть этого языка (используя контейнеры, интеллектуальные указатели и т.д.), Или вы можете найти один из надстроек для сборки мусора.

Если вы хотите сделать это вручную, тщательно определите следующие моменты:

  1. Кто отвечает или создает каждый тип объекта? Надеюсь, короткий список.
  2. Что пользователям разрешено делать с объектом? Лучше сделайте это как можно более однородным.
  3. Кто отвечает за распоряжение объектом? Опять же, надеюсь, короткий список.
  4. Убедитесь, что каждый объект создается один раз и уничтожается один раз на каждом возможном пути, хотя ваш код (т.е. Соответствует (1) и (3), обеспечивает (2) не вмешивается в это)
  5. Поразмышляйте над каждой стрелкой кода, где есть несколько указателей на один и тот же объект. Кто из них "владеет" объектом, является ли "матрос" чистым передачей от одного к другому, если необходимо? Является ли эта сетка хорошо с (1) и (3) выше? Может ли это смутить некоторые из (2), если пройти несколько разных указателей на один и тот же объект?

Настройте общие правила по всем типам объектов, если это возможно (чтобы помнить о разных правилах, гарантирует, что вы в конечном итоге примените неправильные, и в результате получите фейерверк). Некоторые простые правила приведены выше (новый/удалить в той же области, например, убедитесь, что new вызывается только в конструкторах, delete только в деструкторах другой), но они могут быть слишком строгими (объекты в куче и указателях велики именно потому, что время жизни объектов не должно совпадать с кодом).

Рассмотрите возможность использования средств трассировки/отладки выделения памяти, например valgrind. Но не зависеть от них, найти беспорядок и очистить его гораздо больше работы, чем немного планирования заранее. И вы можете не заметить беспорядок в своих тестах, в то время как закон Мерфи гарантирует, что он потерпит крах или иным образом плохо себя ведет в самое худшее время.

0

Проблема с управлением памятью заключается в том, что, хотя она в основном довольно проста (new/new [] → delete/delete []), становится сложнее, когда программа становится более сложной.

Вот почему сначала советуем избегать управления памятью. Это можно сделать, объявив объекты вместо указателей и используя стандартные библиотеки.

Если необходимо, используйте RAII для управления памятью (очистка в деструкторе), в первую очередь умные указатели (std :: unique_ptr, std :: shared_ptr).

Когда вы выполняете управление памятью с помощью (new/delete), выделяете и освобождаете память в той же области, так что легче отслеживать хорошее использование.

Если это действительно необходимо, удаление может быть выполнено в других областях, например, в функциях, но управлять ими может очень сложно.

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

  • 0
    Я думаю, что это может стать проблемой в параллельных программах, не так ли? (Моя программа еще не работает одновременно, но она должна стать параллельной). Я создаю копию структуры данных (объекта) и передаю ее в подфункцию. если эта подфункция выполняется другим потоком, вызывающая функция может завершиться (и удалить данные) до того, как подфункция будет выполнена с ее использованием ?!
  • 0
    Нет, на самом деле, это безопасный способ передачи данных в функции потоков. Новые данные не будут удалены при завершении потока.
Показать ещё 1 комментарий
0

Проблема в том, что вы, вероятно, ссылаетесь на oldObject на свое первоначальное место сразу после вызова подфункции (первоначальный вызов).

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню