Динамически выделенная память должна быть удалена в С++?

Скажем, у меня есть list<TreeNode> в моей программе. Каждый раз, когда я использую new для динамического выделения класса TreeNode и присоединения его к списку; когда программа заканчивается, список исчезает. Однако я не уверен, что все эти элементы, прикрепленные к нему, будут удалены автоматически, когда список исчезнет. Мне все еще нужно самому пройтись по списку и delete всем элементам?

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


person Shanpei Zhou    schedule 11.03.2014    source источник
comment
Поскольку вы не говорили об этом, я полагаю, что вы, возможно, захотите прочитать о smart pointers, если вы еще этого не сделали :-) они связаны с проблемой такого рода.   -  person Natan Streppel    schedule 11.03.2014
comment
Спасибо за ваш совет. Я не читал это раньше.   -  person Shanpei Zhou    schedule 11.03.2014
comment
Если у вас есть list<TreeNode>, вы вообще не будете использовать new. Когда вы вставляете TreeNode в список, значение копируется; а контейнер list заботится об управлении памятью. Вы действительно имели в виду list<TreeNode *>?   -  person M.M    schedule 11.03.2014
comment
@MattMcNabb Я имею в виду список‹TreeNode›. Скажем: TreeNode* temp = new TreeNode; list_t.push_back(*темп).   -  person Shanpei Zhou    schedule 11.03.2014
comment
Затем идите delete temp; сразу после push_back. push_back берет копию *temp. На самом деле вы могли бы просто пойти: Treenode t; list_t.push_back(t); и полностью отказаться от ручного управления памятью.   -  person M.M    schedule 11.03.2014
comment
Да неужели? Я думаю, что контейнеры просто принимают какие-то указатели или ссылки. В памяти только один экземпляр.   -  person Shanpei Zhou    schedule 11.03.2014
comment
list<T> принимает T по значению. В памяти есть две копии после push_back. list<T*> будет принимать указатель. Если вы не верите, то либо прочитайте документацию для std::list, или попробуйте изменить *temp после того, как вы push_back и посмотрите, изменилась ли копия в списке.   -  person M.M    schedule 11.03.2014
comment
@MattMcNabb Ты прав! Большое спасибо. Я очень долго заморачиваюсь по этому поводу :-)   -  person Shanpei Zhou    schedule 11.03.2014


Ответы (3)


Прямо сейчас ваш list<TreeNode> уничтожает себя, потому что программа завершилась, но теперь предположим, что вы находитесь в ситуации, когда вы используете локальные объекты list<TreeNode>, которые создаются и уничтожаются в цикле или что-то подобное. Эта утечка памяти теперь превращается в то, о чем вам нужно беспокоиться.

Суть в том, что ваш код не должен протекать, независимо от ситуации. Единственным исключением может быть синглтон или подобные шаблоны, где может быть какое-то оправдание для того, чтобы позволить объекту «умереть без очистки». Но для чего-то вроде класса списка не должно быть абсолютно никаких утечек.

Кроме того, что, если процесс не должен останавливаться? Что, если это критически важное приложение, которое должно работать 24 часа каждый день? Эта утечка теперь превращается в катастрофу — именно вам или тому (теперь сердитому) коллеге позвонят посреди ночи, пытаясь перезапустить систему из-за исчерпания ресурсов.

person PaulMcKenzie    schedule 11.03.2014
comment
Извините, а что такое локальный список TreeNode? Почему это должно быть проблемой? Все пространство памяти будет освобождено после завершения процесса, поэтому я думаю, что вся эта динамическая память выделения теперь будет доступна для других процессов. - person Shanpei Zhou; 11.03.2014
comment
@user3352668 user3352668 - независимо от того, как вы хотите это сделать, у вашего класса списка нет абсолютно никаких оснований для утечек памяти. Что, если код такой: int main() { for (int i = 0; i < 1000; ++i ) { list<TreeNode> myList; //... } } Предположим, что ... содержит много добавленных узлов -- как вы думаете, что произойдет? - person PaulMcKenzie; 11.03.2014
comment
@user3352668 user3352668 — Но давайте спросим вас — если вы считаете, что утечки памяти — это не плохо, то почему все эти программисты на C++ тратят свое время, пытаясь их исправить? Для чего были разработаны умные указатели? Почему существуют инструменты для проверки утечек памяти? Что за суета? Подумай об этом... - person PaulMcKenzie; 11.03.2014
comment
Ой! Вы имеете в виду, что я должен удалить все узлы в каждом цикле for, иначе во время процесса будет много потерь памяти и, возможно, в какой-то момент процесс рухнет из-за нехватки памяти? - person Shanpei Zhou; 11.03.2014
comment
@ user3352668 - Да. Если вы израсходуете память, где останется работающая программа? Что, если программа должна работать 24 часа в сутки, 7 дней в неделю? Другими словами, нет остановки процесса. - person PaulMcKenzie; 11.03.2014
comment
Большое спасибо! Наконец-то я понял :-) - person Shanpei Zhou; 11.03.2014

Если единственное, что занимает ваш TreeNode, это память, вам не нужно освобождать их при выходе из вашей программы. Однако, если он содержит, скажем, буферизованный файловый поток записи, и вы его не освобождаете, в буфере могут оставаться данные, которые не будут записаны на диск. И тогда у вас будет потеря данных. :-)

P.S. Я должен добавить, что эта стратегия, позволяющая ОС освободить все для вас, применима только в том случае, если ваша программа недолговечна и у вас нет «мусорных» объектов (т. Е. Вам нужно сохранять ссылки на все созданные объекты на время жизни программы) . Если он долгоживущий (но у вас нет мусорных объектов), просто используйте статическую память и не выполняйте динамическое выделение. Если у вас есть мусорные объекты, вам нужно их освободить. Никаких вопросов не было задано. :-)

person Chris Jester-Young    schedule 11.03.2014
comment
если программа выделила слишком много памяти, это может значительно снизить производительность любых других запущенных процессов. - person Bryan Chen; 11.03.2014
comment
@BryanChen Я думаю, что ОП предполагает, что все TreeNode потребуются до выхода программы (подумайте о недолговечной программе, которая просто обрабатывает один XML-документ и завершает работу), и есть ли в этом случае вред в просто выходя из программы, не освобождая узлы. - person Chris Jester-Young; 11.03.2014
comment
Да, все TreeNodes будут нужны до выхода из программы. В этом случае, если TreeNode занимает только память, будет ли то же самое, если я удалю эти объекты? - person Shanpei Zhou; 11.03.2014
comment
@user3352668 user3352668 В этом случае удаление этих объектов необязательно. - person Chris Jester-Young; 11.03.2014
comment
тем не менее, это плохой стиль, позволять программе просачиваться и предполагать, что ОС выполнит очистку после выхода из программы, что может быть слишком поздно. - person Bryan Chen; 11.03.2014
comment
@BryanChen Я согласен, что это плохой стиль, но иногда на самом деле быстрее позволить вашей ОС освободить все в массовом порядке, чем освобождать их по одному. Просто попробуйте выйти из Firefox после открытия 350 вкладок, а не просто убить процесс. (Подсказка: один подход может привести к тому, что множество выгруженных страниц будет возвращено обратно, что не очень полезно.) :-) - person Chris Jester-Young; 11.03.2014
comment
Как насчет того, чтобы попытаться выключить компьютер, отсоединив кабель питания, или использовать команду выключения из ОС? - person Bryan Chen; 11.03.2014
comment
@user3352668 user3352668 Очевидно, мой ответ предполагает, что мы запускаем что-то очень недолговечное, и во время запуска у вас нет мусорных объектов. Если у вас есть мусорные объекты или они долговечны, тогда применим ответ Пола Маккензи. В общем, делайте все бесплатно, но есть ограниченные обстоятельства, когда освобождение необязательно. - person Chris Jester-Young; 11.03.2014
comment
Спасибо, ребята, за ваши советы. - person Shanpei Zhou; 11.03.2014
comment
@BryanChen На самом деле, у меня есть виртуальные устройства, которые я отключаю таким образом. Особенно, если следующее, что я сделаю, это восстановлю из моментального снимка. - person Chris Jester-Young; 11.03.2014

Если вы использовали new для выделения объекта TreeNode каждый раз, когда добавляете его в список, вам придется delete также выделять этот объект, прежде чем ваш list будет очищен.

Одно новое = одно удаление

person Aesthete    schedule 11.03.2014
comment
если вы не используете интеллектуальные указатели, которые вы должны использовать - person Bryan Chen; 11.03.2014
comment
Что ж, ОП сказал, что они используют new, поэтому я просто отвечаю на вопрос, а не сплачиваюсь за подножку умных указателей. - person Aesthete; 11.03.2014