Допустимо ли когда-либо иметь утечка памяти в вашем приложении C или C++?
Что, если вы выделите некоторую память и используете ее до самой последней строчки кода в вашем приложении (например, деструктор глобального объекта)? Если потребление памяти не растет со временем, можно ли доверять ОС, чтобы освободить память для вас, когда ваше приложение завершает работу (в Windows, Mac и Linux)? Вы бы даже сочли это реальной утечкой памяти, если бы память использовалась непрерывно, пока она не была освобождена ОС.
Что, если сторонняя библиотека навязала вам эту ситуацию? Отказались бы использовать эту стороннюю библиотеку, какой бы замечательной она ни была в противном случае?
Я вижу только один практический недостаток: эти незначительные утечки обнаруживаются средствами обнаружения утечек памяти как ложные срабатывания.
Большинство приложений (включая все программы .NET) имеют по крайней мере несколько буферов, которые выделяются один раз и никогда не освобождаются явным образом, поэтому определение mpez0 более полезно.
Да, если у вас бесконечная память.
«Доброкачественная» утечка (если такая есть) не является ложным срабатыванием - это утечка, которая была обнаружена очень правильно. Обнаружение утечек, даже если вы лично не хотите устранять утечки, является единственной причиной существования течеискателя.
@ mpez0 "Если потребление памяти не растет со временем - это не утечка"? Это не определение утечки памяти. Утечка - это утечка памяти, что означает, что она не была освобождена и у вас больше нет ссылки на нее, поэтому вы не можете когда-либо освободить ее снова. Растет он или нет, значения не имеет.





Теоретически нет, на практике По-разному.
Это действительно зависит от того, с каким объемом данных работает программа, как часто программа запускается и работает ли она постоянно.
Если у меня есть быстрая программа, которая считывает небольшой объем данных, производит вычисления и завершает работу, небольшая утечка памяти никогда не будет замечена. Поскольку программа не работает очень долго и использует только небольшой объем памяти, утечка будет небольшой и будет устранена, когда программа существует.
С другой стороны, если у меня есть программа, которая обрабатывает миллионы записей и работает в течение длительного времени, небольшая утечка памяти может вывести машину из строя при наличии достаточного количества времени.
Что касается сторонних библиотек, у которых есть утечки, если они вызывают проблему, либо исправьте библиотеку, либо найдите лучшую альтернативу. Если это не вызывает проблем, какое это имеет значение?
Не знаю, прочитали вы весь мой вопрос или нет. Я говорю, что память используется до самого конца приложения. Со временем не растет. Единственное «нет» - это то, что нет призыва освободить / удалить.
Тогда на самом деле это не утечка памяти. Утечка памяти - это небольшой объем неиспользуемой, но неиспользованной памяти, со временем этот объем увеличивается. То, о чем вы говорите, - это капля памяти. Не беспокойтесь об этом, если ваша капля не очень большая.
"Если это не вызывает проблемы, имеет ли это значение?" Нет, это не имеет значения. Я хочу, чтобы больше людей получили это, вместо того, чтобы становиться религиозными.
@Imbue - не задавайте вопросов, если не хотите, чтобы на них отвечали. Если вас устраивает пул памяти или утечка, запугайте вас. Но многим из нас приходилось работать долгие часы, исправляя ошибки, которые ленивый разработчик решил, что «не вызывает проблем».
@John: Это, как правило, не столько вопрос ленивых разработчиков, сколько вопрос развития программного обеспечения. Мы все делаем ошибки, ошибки - это наша профессия; мы их создаем, мы их исправляем, вот что мы делаем. Это всегда баланс между первоначальными затратами и долгосрочным обслуживанием, этот баланс никогда не бывает однозначным.
Я хочу сказать, что «религия» существует не просто так. Могу ли я представить себе ситуацию, когда я выпущу программное обеспечение с утечкой памяти или пулом? да. Я хочу написать на публичной доске, что это нормально? Нет.
> [T] память используется до самого конца приложения. Если он используется, это не утечка. > Со временем не растет. Рост обычно вызван многократной утечкой одного и того же кода. > [T] здесь не призыв освободить / удалить. Все современные операционные системы освобождают память при выходе из программы.
Ах, форматирование в предыдущем комментарии.
Если вы используете MFC (я предполагаю, что OP, поскольку он упоминает C и C++), утечки памяти в значительной степени неизбежны. Я лично отследил нескольких прямо в MFC, и мне пришлось просто «отпустить». На мой взгляд, ATL лучше, но с ним труднее работать.
@ Джон, это баланс между стоимостью и качеством. На самом деле это действительно просто. Я хочу написать идеальный код? да. Могут ли клиенты позволить себе совершенный код? Как правило, нет или, по крайней мере, для них это не лучший выбор. Это вопрос практичности и реалистичности, здесь допустимы утечки памяти.
хм, я думаю, что я просто противоречил себе, мне следовало выбрать другое слово, а не «прямолинейный» в моем предыдущем комментарии к JohnMcG. Следует, вероятно, прочитать, что баланс никогда не бывает простым.
Джон, я на 100% согласен с тобой .. Imbum Вопрос почти в том, «сколько ты принимаешь». Небрежно - это небрежно .. Как насчет того, чтобы оставить креветку за твоим монитором. вонь есть вонь. Каждый раз, когда мы прогибаемся, наша промышленность немного прогибается. Если вы знаете, что есть утечка, и знаете, что вы ее причиной, то вам следует исправить это.
Я не считаю это утечкой памяти, если только количество «используемой» памяти не растет. Наличие некоторого количества неосвобожденной памяти, хотя и не идеально, не является большой проблемой, если только объем требуемой памяти не будет постоянно расти.
Технически это все еще утечка, потому что остальная часть системы не может использовать эту память.
Технически утечка - это выделенная память, и все ссылки на нее потеряны. Не освобождать память в конце - это просто лениво.
Если у вас однократная утечка памяти на 4 ГБ, это проблема.
Неважно, растет он или нет. Другие программы не могут использовать память, если она у вас выделена.
Но его приложение использует эту память, пока не завершится. Я думаю, он просто имел в виду, что не сохранил начальный указатель, возвращенный из распределения. Объект по-прежнему полезен «до самой последней строчки кода в [] приложении», поэтому его освобождение нежелательно до выхода из приложения.
@sk: Тогда это нормально. Какая бы функция ни использовала память последней, ее следует очистить.
Я думаю, что термин для этой ситуации - это «пул» памяти, фиксирующий, что есть некоторая память, которая не была выделена, но она не увеличивается.
Приложение запускается, оно выделяет память, и указатель сохраняется. Отсюда полдюжины глобальных объектов используют этот указатель постоянно и в своих деконструкторах. Как последняя функция может освободить память?
> Другие программы не могут использовать память, если она у вас выделена. Что ж, ОС всегда может поменять вашу память на диск и разрешить другим приложениям использовать оперативную память, которой вы не пользовались.
Пейджинг - нежелательное состояние. Вы не можете просто позволить своим программам оставаться на той памяти, которую они хотят, и рассчитывать на то, что ОС выручит вас. Если вы освобождаете память, которую не используете, ОС не нужно тратить время на подкачку, что приводит к повышению производительности для всех запущенных приложений.
@Imbue: если вы используете память до завершения программы, значит, вы все делаете правильно.
Если программа очень недолговечная, то утечка может быть не так уж и плоха. Кроме того, хотя это НЕ идеально, разбиение на страницы не так дорого, как некоторые из представленных здесь, потому что программа не интересуется этой памятью (и, следовательно, не будет постоянно менять местами) - если, конечно, у вас нет GC ...
На самом деле это не утечка, если она преднамеренная, и это не проблема, если только это не значительный объем памяти или не может вырасти до значительного объема памяти. Довольно часто глобальные выделения памяти не очищаются в течение жизненного цикла программы. Если утечка происходит на сервере или в давно работающем приложении и со временем растет, то проблема в этом.
Я уверен, что кто-то может придумать повод, чтобы сказать «да», но не я. Вместо того, чтобы сказать «нет», я скажу, что это не должен быть вопрос «да / нет». Есть способы управлять или сдерживать утечки памяти, и они есть во многих системах.
Есть системы НАСА на устройствах, которые покидают Землю, которые планируют это. Системы будут время от времени автоматически перезагружаться, чтобы утечки памяти не стали фатальными для всей работы. Просто пример сдерживания.
На самом деле это пример старения программного обеспечения. Увлекательный предмет изучения.
Автоматическая перезагрузка время от времени, а? НАСА, а? (* смотрит на старые установочные компакт-диски Microsoft Windows *) Это многое объясняет ...
Думаю, вы ответили на свой вопрос. Самый большой недостаток заключается в том, как они мешают работе инструментов обнаружения утечек памяти, но я думаю, что этот недостаток является ОГРОМНЫМ недостатком для определенных типов приложений.
Я работаю с устаревшими серверными приложениями, которые должны быть надежными, но в них есть утечки, а глобальные переменные НЕ ДОЛЖНЫ мешать инструментам обнаружения памяти. Это большая сделка.
В книге Джареда Даймонда «Коллапс» автор задается вопросом, о чем думал тот парень, который срубил последнее дерево на острове Пасхи, дерево, которое ему понадобилось бы, чтобы построить каноэ, чтобы спуститься с острова. Интересно, как много лет назад этот первый глобал был добавлен в нашу кодовую базу. В ЭТОТ день его должны были поймать.
Нет ничего плохого в том, чтобы очистить ОС после запуска приложения.
Это действительно зависит от приложения и от того, как оно будет запускаться. Необходимо позаботиться о постоянно возникающих утечках в приложении, которое должно работать в течение нескольких недель, но небольшой инструмент, который вычисляет результат без слишком большой потребности в памяти, не должен быть проблемой.
Есть причина, по которой многие языки сценариев не собирают циклические ссылки «сборщик мусора»… для их шаблонов использования это не актуальная проблема и, следовательно, будет такой же пустой тратой ресурсов, как и потраченная впустую память.
О языках сценариев: Python использует счетчик ссылок, но имеет сборщик мусора только для освобождения циклических ссылок. В других языках программист часто вообще избегает явно циклических ссылок, что создает другие проблемы.
Более ранние версии PHP не освобождали память, они просто работали от начала до конца, увеличивая объем памяти - обычно через 0,1 секунды времени выполнения сценарий завершался, и вся память была освобождена.
Я вижу ту же проблему, что и все вопросы сценария вроде этого: что происходит, когда программа изменяется, и внезапно эта небольшая утечка памяти вызывается десять миллионов раз, а конец вашей программы находится в другом месте, так что это имеет значение? Если он находится в библиотеке, сообщите об ошибке сопровождающим библиотеки, не допускайте утечек в свой код.
В этом случае влияние утечки памяти меняется, и вам необходимо переоценить приоритет устранения утечки.
@John: Тогда тебе лучше хотя бы задокументировать утечку. Даже в этом случае я бы не стал доверять кому-то, чтобы он все равно не проигнорировал большой красный мигающий комментарий и скопировал и вставил дырявый код. Я предпочитаю вообще не давать кому-то такую возможность.
Я отвечу нет.
Теоретически операционная система очистится после вас, если вы оставите беспорядок (сейчас это просто грубо, но, поскольку у компьютеров нет чувств, это может быть приемлемо). Но вы не можете предвидеть все возможные ситуации, которые могут возникнуть при запуске вашей программы. Поэтому (если вы не можете провести формальное доказательство некоторого поведения) создание утечек памяти просто безответственно и небрежно с профессиональной точки зрения.
Если сторонний компонент дает утечку памяти, это очень веский аргумент против его использования не только из-за неминуемого эффекта, но и потому, что он показывает, что программисты работают небрежно и что это также может повлиять на другие показатели. Теперь, когда речь идет о устаревших системах, это сложно (рассмотрите компоненты просмотра веб-страниц: насколько мне известно, у них утечка памяти все), но это должно быть нормой.
это настолько специфично для предметной области, что на него вряд ли стоит отвечать. используй свою долбаную голову.
и есть спектр промежуточных ситуаций.
Альтернативные издержки ($$$) задержки выпуска продукта для устранения всех утечек памяти, кроме худших, обычно затмевают любое чувство «небрежности или непрофессионализма». Ваш босс платит вам, чтобы заработать ему деньги, а не за то, чтобы испытывать теплые, туманные чувства.
Очень недальновидное отношение. Вы в основном говорите, что нет необходимости использовать принципиально правильные методы программирования, пока не будет обнаружен дефект, вызванный этими методами. Проблема в том, что программное обеспечение, написанное с использованием неаккуратных методов, имеет больше дефектов, чем программное обеспечение, в котором их нет.
Я не верю всему этому. А управление памятью сложнее, чем писать чистые методы.
Дастин, очевидно, работает в реальном мире, как и большинство из нас, где мы постоянно работаем с безумными сроками, чтобы не отставать от конкурентов. Так что исправлять ошибки нужно прагматично. Тратя слишком много времени на незначительные ошибки в неважных программах, вы не добьетесь своей цели.
Проблема с таким отношением: когда вы начинаете устранять утечки? «Хорошо, это силовая установка, но это просто уголь, а не уран. Зачем устранять утечки здесь?» - В реальном мире я узнал, что если вы не делаете правильные вещи с самого начала, все время, этого просто не произойдет. Такое отношение порождает проекты, которые завершаются на 99% через две недели и остаются таковыми в течение двух месяцев.
Планируете ли вы исправить проблемы, если у вас их куча, одна на другой?
Если вы выделяете память и используете ее до последней строки вашей программы, это не утечка. Если вы выделяете память и забываете об этом, даже если объем памяти не увеличивается, это проблема. Эта выделенная, но неиспользуемая память может привести к тому, что другие программы будут работать медленнее или вообще не работать.
Не совсем, поскольку, если он не используется, он просто выгружается. Когда приложение закрывается, вся память освобождается.
Пока он выделен, другие программы не смогут его использовать. Он не будет выгружен, если вы его не освободите.
Конечно, будет - вот что такое виртуальная память. У вас может быть 1 ГБ реальной оперативной памяти и при этом иметь 4 процесса, каждый из которых полностью выделяет 2 ГБ виртуальной памяти (при условии, что ваш файл подкачки достаточно велик).
Конечно, вы столкнетесь с серьезными проблемами подкачки, если каждый из этих процессов будет активно использовать всю эту память.
Хорошо, я понимаю, о чем вы сейчас говорите. Если вы освободите память, которую не используете, вы уменьшите потребность в подкачке страниц. Если вы оставите его выделенным, ваше приложение все равно сохранит его, когда оно будет загружено обратно.
Вы должны сначала понять, что есть большая разница между предполагаемой утечкой памяти и реальной утечкой памяти. Очень часто инструменты анализа сообщают о множестве отвлекающих факторов и отмечают утечку чего-либо (память или ресурсы, такие как дескрипторы и т. д.) Там, где на самом деле это не так. Часто это связано с архитектурой инструмента анализа. Например, некоторые инструменты анализа будут сообщать об объектах времени выполнения как об утечках памяти, поскольку они никогда не обнаруживают, что эти объекты освобождены. Но освобождение происходит в коде выключения среды выполнения, который инструмент анализа может не увидеть.
С учетом сказанного, все равно будут моменты, когда у вас будут фактические утечки памяти, которые либо очень трудно найти, либо очень трудно исправить. Итак, теперь возникает вопрос, можно ли когда-нибудь оставлять их в коде?
Идеальный ответ - «нет, никогда». Более прагматичный ответ может быть «нет, почти никогда». Очень часто в реальной жизни у вас ограниченное количество ресурсов и времени для решения и бесконечный список задач. Когда одной из задач является устранение утечек памяти, очень часто срабатывает закон убывающей отдачи. Вы можете устранить, скажем, 98% всех утечек памяти в приложении за неделю, но оставшиеся 2% могут занять месяцы. В некоторых случаях может быть даже невозможно устранить определенные утечки из-за архитектуры приложения без серьезного рефакторинга кода. Вы должны взвесить затраты и выгоды от устранения оставшихся 2%.
Думаю, в вашей ситуации ответ может быть таким, что все в порядке. Но вам обязательно нужно задокументировать, что утечка памяти - это сознательное решение. Вы же не хотите, чтобы программист сопровождения приходил, вставлял ваш код в функцию и вызывал ее миллион раз. Поэтому, если вы решите, что утечка допустима, вам необходимо задокументировать ее (БОЛЬШИМИ БУКВАМИ) для тех, кому, возможно, придется работать над программой в будущем.
Если это сторонняя библиотека, вы можете попасть в ловушку. Но обязательно задокументируйте, что эта утечка происходит.
Но в основном, если утечка памяти известна как буфер размером 512 КБ или что-то в этом роде, тогда это не проблема. Если утечка памяти продолжает расти, как и каждый раз, когда вы вызываете вызов библиотеки, ваша память увеличивается на 512 КБ и не освобождается, тогда у вас может быть проблема. Если вы задокументируете это и контролируете количество раз, когда вызов будет выполнен, им можно будет управлять. Но тогда вам действительно нужна документация, потому что, хотя 512 - это немного, 512 более миллиона вызовов - это много.
Также вам необходимо проверить документацию по вашей операционной системе. Если это встроенное устройство, могут быть операционные системы, которые не освобождают всю память из программы, которая завершает работу. Я не уверен, может, это неправда. Но на это стоит посмотреть.
«Но вам определенно необходимо документально подтвердить, что утечка памяти - это сознательное решение». Слава богу. Лучшее, что было сказано до сих пор.
Я согласен с vfilby - смотря как. В Windows мы относимся к утечкам памяти как к относительно серьезным ошибкам. Но это очень сильно зависит от компонента.
Например, утечки памяти не очень серьезны для компонентов, которые запускаются редко и в течение ограниченных периодов времени. Эти компоненты запускаются, выполняют свою работу, а затем закрываются. Когда они выходят, вся их память неявно освобождается.
Однако утечки памяти в службах или других долгосрочных компонентах (например, оболочке) очень серьезны. Причина в том, что эти ошибки со временем «крадут» память. Единственный способ исправить это - перезапустить компоненты. Большинство людей не знают, как перезапустить службу или оболочку, поэтому, если производительность их системы снижается, они просто перезагружаются.
Итак, если у вас есть утечка - оцените ее влияние двумя способами.
Foredecker
3. Влияние на обслуживание программного обеспечения.
Исторически это имело значение для некоторых операционных систем в некоторых крайних случаях. Эти крайние случаи могут существовать в будущем.
Вот пример, в SunOS в эпоху Sun 3 возникла проблема, если процесс использовал exec (или, более традиционно, fork, а затем exec), последующий новый процесс унаследовал тот же объем памяти, что и родительский, и его нельзя было сжать . Если родительский процесс выделил 1/2 гигабайта памяти и не освободил ее перед вызовом exec, дочерний процесс начал бы использовать те же 1/2 гигабайта (даже если он не был выделен). Такое поведение лучше всего демонстрировал SunTools (их оконная система по умолчанию), которая потребляла много памяти. Каждое созданное им приложение создавалось с помощью fork / exec и унаследовало след SunTools, быстро заполняя пространство подкачки.
Нет.
Как профессионалы, мы не должны задавать себе вопрос: «Можно ли когда-нибудь это делать?» а скорее "Есть ли причина для этого хорошо?" И «выслеживать эту утечку памяти - боль» - не лучший повод.
Я люблю все упрощать. И простое правило - моя программа не должна иметь утечек памяти.
Это тоже упрощает мою жизнь. Если я обнаруживаю утечку памяти, я ее устраняю, а не просматриваю сложную древовидную структуру решений, чтобы определить, является ли это «приемлемой» утечкой памяти.
Это похоже на предупреждения компилятора - будет ли предупреждение фатальным для моего конкретного приложения? Возможно, нет.
Но в конечном итоге это вопрос профессиональной дисциплины. Терпеть предупреждения компилятора и терпеть утечки памяти - плохая привычка, которая в конечном итоге укусит меня в тыл.
Если довести дело до крайности, будет ли приемлемым для хирурга когда-либо оставлять какое-либо операционное оборудование внутри пациента?
Хотя возможно, что могут возникнуть обстоятельства, при которых стоимость / риск удаления этого элемента оборудования превышает стоимость / риск его оставления, и могут быть обстоятельства, при которых оно было безвредным, если бы я увидел этот вопрос, размещенный на SurgeonOverflow.com и если бы я увидел любой ответ, кроме «нет», это серьезно подорвало бы мое доверие к медицинской профессии.
-
Если бы сторонняя библиотека навязала мне эту ситуацию, это заставило бы меня серьезно подозревать общее качество рассматриваемой библиотеки. Это было бы так, как если бы я тестировал машину и обнаружил пару незакрепленных шайб и гаек в одном из подстаканников - это может не иметь большого значения, но это отражает отсутствие приверженности к качеству, поэтому я бы рассмотрел альтернативы.
Правда и неправда одновременно. Абсолютное большинство из нас - рабы по заработной плате, и любое стремление к мастерству должно отойти на второй план по сравнению с требованиями бизнеса. Если в этой сторонней библиотеке есть утечка и она экономит 2 недели работы, возможно, есть экономическое обоснование для ее использования и т. д.
Я бы все равно использовал библиотеку, если бы это было что-то, что мне нужно, и не было бы достойных альтернатив, но я бы зарегистрировал ошибку с сопровождающими.
Хотя лично я бы дал точно такой же ответ, есть программы, которые почти не освобождают память. Причина в том, что они: а) предназначены для работы в операционных системах, которые освобождают память, и б) предназначены для работы не очень долго. Действительно, редкие ограничения для программы, но я принимаю это как совершенно верное.
Практически все основные ОС освобождают память, за исключением случаев, когда у вас есть общие объекты InterProcess и для них используется подсчет ссылок (например, COM в Windows). Даже DOS, я думаю, освободила память. Мне было бы любопытно узнать об исключениях :-)
Это нормальный ответ, но OP описывает (возможно) программу с неэффективной памятью, а не утечку памяти.
Например, python был (есть?) печально известен утечкой памяти. было бы глупо не использовать его из принципа.
Чтобы добавить несколько причин для ранней проверки: когда ваши инструменты отладки переполнены «доброкачественными» утечками, как вы собираетесь найти «настоящую» утечку? Если вы добавите пакетную функцию, и внезапно ваша утечка 1 КБ / час станет 1 КБ / сек?
@Dustin: Как и в C++, в python сложно управлять памятью при наличии циклов ссылок из-за используемой схемы подсчета ссылок.
Хм, "без утечки памяти" "идеально"?
@JohnMcG - об утечках памяти; да. Совершенно: полная в своем роде, без дефектов.
Что касается смертей, наличие живого пациента в конце операции тоже «идеально».
@JohnMcG: Если бы ваша программа поддерживала свой собственный пул памяти (например), вы действительно потрудились бы освободить свободный список перед выходом из программы? Я не сомневаюсь в твоих навыках профессионала, но если бы я платил за твои услуги, я бы посчитал это ненужным золотым покрытием.
* читает ответ * * доходит до строки I like to keep things simple. And the simple rule is that my program should have no memory leaks. * * нажимает на голосование *
Хотя некоторые моменты верны, это экстремистский ответ. Как профессионалы, мы обязаны производить продукт. Пожалуйста, не стесняйтесь писать всем блестящим err, извините, «ленивым» разработчикам, стоящим за boost, и сказать им, что они не являются хорошими профессионалами или программистами, прежде чем из коробки boost напечатает мне книгу предупреждений компилятора.
Как известно большинству из вас, часто бывает некоторая ограниченность во времени. Хотя я полностью согласен с тем, что утечки памяти - это плохо и иногда утомительно, я бы предпочел задать себе следующий вопрос; Стоит ли отслеживать эту утечку памяти затрат на это? Или сколько времени мне нужно потратить на репликацию этой прекрасной библиотеки с утечкой памяти? Кроме того, обязательно должна быть лучше другая библиотека без утечек? Так что должны быть проблемы, с которыми вам, возможно, придется смириться. Однако он должен быть небольшим. Попробуйте поискать по техническому долгу.
Очевидно, поздно, но я поражен тем, как многие продолжают пытаться рационализировать свои утечки памяти и другие вредные привычки, вместо того, чтобы признать тот факт, что они не должен это делают. Тот факт, что мы можем быть «наемными рабами», не имеет значения. Строительные рабочие также являются «наемными рабами», и я серьезно сомневаюсь, что кто-то попытается рационализировать плохие практики в гражданском строительстве, поставив под угрозу качество строительства. Всегда есть «экономическое обоснование» для использования «ярлыков». Имейте в виду, что вы все работаете на клиент, который платит вам за вашу работу должным образом.
@ray Согласен. Проблема в том, что мы продолжаем позволять менеджерам уходить от дела, призывая разработчиков сокращать путь и экономить на контроле качества, потому что все всегда должно быть доставлено вчера, и мало кто, похоже, смотрит не только на краткосрочные затраты на разработку, но и на затраты на долгосрочное обслуживание. В гражданском строительстве, когда рушится мост или здание, каждый видит разрушения и кровавую бойню. В программном обеспечении, когда процесс умирает из-за утечки памяти каждые два дня, мы пишем сценарий, чтобы перезапустить его в одночасье или попросить «серверного парня» перезагрузить его. По крайней мере, это хороший бизнес для авторов инструментов мониторинга.
@G_H Может быть, более глубокая проблема в том, что (как правило) некомпетентные боссы продолжают оставаться некомпетентными / невежественными в том, чем они управляют. Раньше у меня был начальник, который действительно думал, что то, что мне нужно, было «простым» просто потому, что он мог выразить свои потребности простыми словами. Судя по его рассуждениям, я бы не удивился, если бы он подумал, что такой запрос, как «Мне нужна кнопка, которая может решить все мои проблемы», тоже должен быть куском пирога. Моим решением было бы, чтобы программа предоставляла пользователю пистолет с одной пулей, но я отвлекся.
@ray Это настолько мучительно верно, что я даже не могу заставить себя полностью прокомментировать это прямо сейчас. Технические менеджеры должны иметь технический опыт, но, похоже, именно те, кто не увлечен программированием и разработкой программного обеспечения, хотят как можно скорее подняться по служебной лестнице, чтобы выбраться из «окопов кодирования».
@ray - Ссылка на строительную отрасль как на образец нетерпимости к плохой практике, по меньшей мере, наивна.
@ray - «когда обрушивается мост или здание, все видят ущерб и бойню» несколько упускают из виду сам смысл, потому что такого рода катастрофические отказы являются исключением из более коварной нормы, как и в мире программного обеспечения. В мире полно мостов и зданий, которые не рухнули, но были плохо построены и демонстрируют структурные дефекты, требующие различной степени обслуживания и ремонта для поддержания их работоспособности - аналогично периодической перезагрузке сервера. И явно кто-то, где-то, сделал рационализирует - по крайней мере, для себя - делая это таким образом.
@Jeremy Я подведу итоги и надеюсь, что мне не придется вдаваться в подробности, кроме этого: это была аналогия; нет идеальной аналогии. Тем не менее, утечки памяти делают программы непригодными для использования и могут (в конечном итоге) обрушить всю систему на колени или привести к остановке процесса, подобно тому, как плохо построенные здания могут стать непригодными для использования или даже разрушиться. Дело в том, что когда ОС убивает процесс, никто не бьет глазом, но когда здания рушатся, все теряют рассудок. Инженеры могут даже потерять свои лицензии (в США), поэтому не уничтожать свою карьеру - неважно делать это правильно с первого раза.
Я полностью согласен с JohnMcG и просто хочу добавить, что у меня самого были проблемы с обнаружением реальных, потенциально серьезных утечек памяти во времени только потому, что было принято иметь доброкачественные утечки. Когда со временем их стало так много, становится все труднее обнаружить серьезные в потоке доброкачественных.
Так что, по крайней мере, ради своих товарищей-программистов (а также ради себя в будущем), пожалуйста, постарайтесь как можно скорее исключить их.
В этом вопросе контекст - все. Лично я терпеть не могу утечки, и в своем коде я иду на все, чтобы исправить их, если они возникают, но не всегда стоит исправлять утечку, и когда люди платят мне по часам, я иногда сказал им, что исправление утечки в их коде не стоит моих денег. Позволь мне привести пример:
Я оценивал проект, выполнял некоторую работу по производительности и исправлял множество ошибок. Во время инициализации приложений произошла утечка, которую я отследил и полностью понял. Чтобы исправить это должным образом, потребовался бы день или около того на рефакторинг фрагмента функционального кода. Я мог бы сделать что-нибудь хакерское (например, вставить значение в глобал и захватить его в какой-то момент, я знаю, что оно больше не использовалось для бесплатного использования), но это только вызвало бы больше замешательства у следующего парня, который должен был коснуться кода.
Лично я изначально не стал бы писать код таким образом, но большинству из нас не всегда удается работать с первозданными, хорошо спроектированными кодовыми базами, и иногда вам нужно смотреть на эти вещи прагматично. Время, которое мне потребовалось бы, чтобы исправить эту 150-байтовую утечку, вместо этого можно было бы потратить на усовершенствования алгоритмов, которые сократили бы мегабайты оперативной памяти.
В конечном итоге я решил, что утечка 150 байтов для приложения, которое использовалось около гигабайта оперативной памяти и работало на выделенной машине, не стоит исправления, поэтому я написал комментарий, в котором говорилось, что утечка произошла, что нужно изменить, чтобы исправить это и почему в то время оно того не стоило.
Умный. Тем более, что утечка произошла во время инициализации, а это значит, что она не будет накапливаться во время выполнения приложения.
Даже если вы уверены, что ваша «известная» утечка памяти не вызовет хаоса, не делайте этого. В лучшем случае это позволит вам совершить аналогичную и, возможно, более серьезную ошибку в другое время и в другом месте.
Для меня этот вопрос похож на вопрос: «Могу ли я выключить красный свет в 3 часа ночи, когда никого нет рядом?». Конечно, в то время это может не вызвать никаких проблем, но даст вам рычаг, чтобы сделать то же самое в час пик!
Я могу по пальцам пересчитать количество «безвредных» утечек, которые я наблюдал за долгое время.
Так что ответ - однозначное «да».
Пример. Если у вас есть одноэлементный ресурс, которому нужен буфер для хранения кольцевой очереди или двухсторонней очереди, но он не знает, насколько большим должен быть буфер, и не может позволить себе накладные расходы на блокировку или каждый считыватель, то выделение буфера экспоненциально удваивающегося, но не освобождение старых приведет к утечке ограниченного объема памяти на каждую очередь / двухстороннюю очередь. Их преимущество в том, что они значительно ускоряют каждый доступ и могут изменить асимптотику многопроцессорных решений, никогда не рискуя конкуренцией за блокировку.
Я видел, как этот подход использовался с большой пользой для вещей с очень четко фиксированными счетчиками, такими как deques для каждого процессора, и в гораздо меньшей степени в буфере, используемом для хранения одноэлементного состояния /proc/self/maps в консервативном сборщике мусора Hans Boehm для C / C++, который используется для определения корневых наборов и т. д.
Хотя технически это утечка, оба этих случая ограничены по размеру, и в случае растущей циклической обработки перехватов двухсторонней очереди достигается выигрыш в производительности огромный в обмен на ограниченное увеличение использования памяти для очередей в 2 раза.
Вы можете использовать указатели опасности, чтобы предотвратить утечку.
Если вы выделяете кучу кучи в начале своей программы и не освобождаете ее при выходе, это не утечка памяти как таковая. Утечка памяти - это когда ваша программа перебирает часть кода, и этот код выделяет кучу, а затем «теряет след», не освобождая ее.
Фактически, нет необходимости звонить в free () или удалить прямо перед выходом. Когда процесс завершается, вся его память освобождается ОС (это, безусловно, относится к POSIX. В других ОС - особенно встроенных - YMMV).
Единственное предостережение, которое я хотел бы сделать, чтобы не освобождать память во время выхода, заключается в том, что если вы когда-нибудь реорганизуете свою программу так, чтобы она, например, стала службой, которая ожидает ввода, делает то, что делает ваша программа, а затем зацикливается на еще один сервисный вызов, затем то, что вы закодировали может, превращается в утечку памяти.
Позволю себе не согласиться. Это является «утечка памяти как таковая».
Это не утечка, пока вы не «потеряете» ссылку на объект. Предположительно, если память используется на время жизни программы, то утечки не происходит. Если ссылка не потеряна до вызова exit (), то это абсолютно нет утечка.
Amiga DOS была последней операционной системой, на которую я смотрел, которая не убирала позади процессы. Однако имейте в виду, что разделяемую память System V IPC можно оставить, даже если никакой процесс ее не использует.
Palm не освобождает «просочившуюся» память до тех пор, пока вы не выполните горячую синхронизацию. это пришло хорошо после амиги. Я запускал приложения на своем эмуляторе ладони, у которых были утечки ... Они никогда не попадали на мою настоящую ладонь.
Это уже обсуждалось до тошноты. Суть в том, что утечка памяти является ошибкой и должна быть исправлена. Если сторонняя библиотека дает утечку памяти, это заставляет задуматься, что еще с ней не так, не так ли? Если бы вы строили автомобиль, использовали бы вы двигатель, из которого иногда вытекает масло? В конце концов, двигатель сделал кто-то другой, так что это не ваша вина и вы не можете его починить, верно?
Но если у вас есть автомобиль с двигателем, в котором время от времени происходит утечка масла, тратите ли вы деньги на его ремонт или следите за уровнями масла и время от времени доливаете его. Ответ зависит от множества факторов.
Речь не идет о владении автомобилем. Речь идет о постройке машины. Если у вас есть сторонняя библиотека с утечками памяти и вам абсолютно необходимо ее использовать, то вы с ней живете. Но если вы пишете систему или библиотеку, вы обязаны убедиться, что в ней нет ошибок.
+1 относитесь к нему как к любому другому багу. (В моей книге это не означает "исправить немедленно", но "необходимо исправить" наверняка)
Как правило, утечка памяти в автономном приложении не является фатальной, поскольку она очищается при выходе из программы.
Что вы делаете для серверных программ, которые не закрываются?
Если вы из тех программистов, которые не разрабатывают и не реализуют код, в котором ресурсы распределяются и высвобождаются правильно, то я не хочу иметь ничего общего с вами или вашим кодом. Если вы не хотите очищать утечку памяти, как насчет ваших замков? Вы тоже оставляете их там болтаться? Вы оставляете кучу временных файлов в разных каталогах?
Слить эту память и позволить программе очистить ее? Нет. Абсолютно нет. Это плохая привычка, которая приводит к ошибкам, ошибкам и еще большему количеству ошибок.
Убирайся за собой. Йо, мама, здесь больше не работает.
Я работал над серверными программами, которые намеренно используют процессы, а не потоки, поэтому утечки памяти и ошибки сегментации вызывают ограниченный ущерб.
Интересный подход. Я был бы немного обеспокоен процессами, которые не могут завершиться и продолжают поглощать память.
Похоже, ваше определение «утечки памяти» - это «память, которую я не очищаю сам». Все современные ОС освобождают его при выходе из программы. Однако, поскольку это вопрос C++, вы можете просто обернуть рассматриваемую память в соответствующий std::auto_ptr, который вызовет delete, когда он выйдет за пределы области видимости.
Давайте сначала уточним наши определения. Память утечка - это когда память распределяется динамически, например, с malloc(), и все ссылки на память теряются без соответствующего свободного места. Простой способ сделать такой:
#define BLK ((size_t)1024)
while(1){
void * vp = malloc(BLK);
}
Обратите внимание, что каждый раз во время цикла while (1) выделяется 1024 (+ служебные) байта, и новый адрес назначается vp; не осталось указателя на предыдущие заблокированные блоки. Эта программа гарантированно будет работать до тех пор, пока не закончится куча, и нет никакого способа восстановить какую-либо память, заблокированную в памяти. Память «утекает» из кучи, и никогда больше ее не увидишь.
Однако то, что вы описываете, звучит как
int main(){
void * vp = malloc(LOTS);
// Go do something useful
return 0;
}
Вы выделяете память, работаете с ней, пока программа не завершится. Это нет утечка памяти; это не влияет на работу программы, и вся память будет очищена автоматически, когда программа завершится.
Как правило, следует избегать утечек памяти. Во-первых, потому что, как и высота над вами и топливо в ангаре, утечка памяти, которая не может быть восстановлена, бесполезна; во-вторых, гораздо проще правильно кодировать без утечки памяти в начале, чем потом обнаруживать утечку памяти.
Теперь рассмотрим несколько десятков таких распределений. Теперь подумайте о том, что нужно переместить «основное» тело в подпрограмму, которая вызывается несколько раз. Наслаждаться. - Я согласен с мнением, что в этом сценарии нет такой большой проблемы, но сценарии меняются. Как говорится, всегда пишите код так, будто парень, который его поддерживает, знает, где вы живете.
Дело в том, что память, которая заблокирована и удерживается до тех пор, пока программа не вызовет _exit (), не «просочилась».
Это утечка памяти, которая может повредить вашу программу. В результате этого процесса при выделении памяти в будущем может произойти сбой, потому что я уверен, что вы проверяете, что malloc везде возвращает ненулевое значение. из-за чрезмерного использования памяти, например, во встроенной ситуации, когда память не хватает, это может быть разницей между жизнью и смертью.
Майк, это неправда. В совместимой среде C завершение main освобождает все ресурсы процесса. Во встроенной среде, как вы описываете, вы могли бы увидеть эту ситуацию, но у вас не было бы файла main. Теперь я допускаю, что могут быть некорректные встроенные среды, для которых это было бы неверно, но потом я видел ошибочные среды, которые тоже не могли правильно справиться с + =.
Верно - до тех пор, пока ваш код не будет перенесен в метод класса и создан 1000 раз. Тогда у вас есть код, который буквально кровоточит из 1000 ран.
Да, теперь вы обнаружили, что если у вас malloc слишком много памяти, это плохо. Это все еще не утечка. Это не утечка до тех пор, пока это не память mallocd, ссылка на которую потеряна.
@CharlieMartin: Я привык к / * noreturn * / void main () во встроенных средах.
@ Джошуа, да, и это немного странно. Я был бы удивлен, если бы return 0 вызвал проблему. В ужасе, правда.
@ Чарли: Хорошо, если вы хотите остановить встроенную среду. (Подсказка: нет.)
@Joshua Вообще-то, я немного удивлен встроенной программой с main. О какой среде вы думаете?
@CharlieMartin: Микрочип. У него был код запуска ASM, который вызывал main () без параметров. Возврат из main () перешел в бесконечный цикл.
@ Джошуа Хорошо. Думаю, я бы назвал это недостатком дизайна или ошибкой - я бы подумал ... черт возьми, я не знаю, что бы подумать. Не похоже, что main все равно не вернется, когда вы дойдете до }. Вам приходилось записывать while(1) внутри main?
Я считаю, что ответ - нет, никогда не допускать утечки памяти, и у меня есть несколько причин, о которых я не видел явно. Здесь есть отличные технические ответы, но я думаю, что настоящий ответ зависит от более социальных / человеческих причин.
(Во-первых, обратите внимание, что, как уже упоминалось, настоящая утечка - это когда ваша программа в любой момент теряет отслеживание ресурсов памяти, которые она выделила. В C это происходит, когда вы malloc() на указатель и позволяете этому указателю покинуть область, не выполняя сначала free().)
Важной составляющей вашего решения здесь является привычка. Когда вы пишете код на языке, который использует указатели, вы собираетесь использовать указатели много. А указатели опасны; это самый простой способ добавить в код всевозможные серьезные проблемы.
Когда вы кодируете, иногда вы будете в курсе событий, а иногда вы будете уставать, злиться или беспокоиться. В те моменты, когда вы несколько отвлекаетесь, вы больше программируете на автопилоте. Эффект автопилота не различает одноразовый код и модуль в более крупном проекте. В это время привычки, которые вы устанавливаете, в конечном итоге войдут в вашу базу кода.
Так что нет, никогда не допускайте утечек памяти по той же причине, по которой вы все равно должны проверять слепые зоны при смене полосы движения, даже если в данный момент вы единственный автомобиль на дороге. В периоды, когда ваш активный мозг отвлекается, хорошие привычки - это все, что может спасти вас от катастрофических ошибок.
Помимо проблемы «привычки», указатели сложны и часто требуют больших умственных способностей для мысленного отслеживания. Лучше не «мутить воду», когда дело касается использования указателей, особенно если вы новичок в программировании.
Есть и более социальный аспект. При правильном использовании malloc() и free() любой, кто посмотрит на ваш код, почувствует себя непринужденно; вы управляете своими ресурсами. Если вы этого не сделаете, они сразу же заподозрят проблему.
Возможно, вы уже выяснили, что утечка памяти ничему не повредит в этом контексте, но каждый сопровождающий вашего кода тоже должен будет продумать это в своей голове, когда он будет читать этот фрагмент кода. Используя free(), вы избавляетесь от необходимости даже рассматривать проблему.
Наконец, программирование - это запись ментальной модели процесса на однозначном языке, чтобы человек и компьютер могли полностью понять этот процесс. Жизненно важная часть хорошей практики программирования - никогда не вносить ненужную двусмысленность.
Умное программирование является гибким и универсальным. Плохое программирование неоднозначно.
Мне нравится идея привычки. Я тоже согласен. Если я вижу утечку памяти, мне всегда интересно, какой еще угол прорезал кодер. Особенно если это очевидно
На сегодняшний день это лучший ответ. Я программирую на C++ уже 5 лет и ни разу не написал ни одной утечки памяти. Причина в том, что я не пишу код, который имеет тенденцию к утечке памяти. В хорошем дизайне C++ вы редко используете new, поэтому большинство утечек памяти сразу же устраняется. Только в случае крайней необходимости используйте new. Результат этого new должен быть немедленно помещен в интеллектуальный указатель. Если вы будете следовать этим двум правилам, у вас просто никогда не будет утечки памяти (за исключением ошибки в библиотеке). Единственный оставшийся случай - это циклы shared_ptr, и в этом случае вы должны знать, как использовать weak_ptr.
Многие люди думают, что как только вы освобождаете память, она мгновенно возвращается в операционную систему и может использоваться другими программами.
Это неправда. Операционные системы обычно управляют памятью на страницах по 4 КиБ. malloc и другие средства управления памятью получают страницы из ОС и управляют ими по своему усмотрению. Вполне вероятно, что free() будет возвращать страницы в операционную систему с помощью нет, при условии, что ваша программа позже выделит больше памяти.
Я не говорю, что free() никогда не возвращает память операционной системе. Это может случиться, особенно если вы освобождаете большие участки памяти. Но нет никаких гарантий.
Важный факт: Если вы не освобождаете память, которая вам больше не нужна, дальнейшие маллоки гарантированно потребляют память даже больше. Но если вы сначала освободите, malloc может вместо этого повторно использовать освобожденную память.
Что это значит на практике? Это означает, что если вы знаете, что ваша программа с этого момента не будет требовать больше памяти (например, она находится на этапе очистки), освобождение памяти не так важно. Однако, если программа может выделить больше памяти позже, вам следует избегать утечек памяти, особенно тех, которые могут происходить неоднократно.
Также см. этот комментарий для более подробной информации о том, почему освобождение памяти непосредственно перед завершением - это плохо.
Комментатор, похоже, не понял, что вызов free() не позволяет автоматически использовать освобожденную память другим программам. Но в этом весь смысл этого ответа!
Итак, чтобы убедить людей, я продемонстрирую пример, в котором free () приносит очень мало пользы. Чтобы упростить математику, я представлю, что операционная система управляет памятью на страницах по 4000 байтов.
Предположим, вы выделяете десять тысяч 100-байтовых блоков (для простоты я проигнорирую дополнительную память, которая потребуется для управления этим распределением). Это занимает 1 МБ или 250 страниц. Если вы затем освободите 9000 этих блоков случайным образом, у вас останется только 1000 блоков, но они разбросаны повсюду. По статистике около 5 страниц будут пустыми. В остальных 245 будет по крайней мере один выделенный блок. Это составляет 980 КБ памяти, которую операционная система не может освободить, даже если теперь у вас выделено только 100 КБ!
С другой стороны, теперь вы можете malloc () еще 9000 блоков, не увеличивая объем памяти, который ваша программа связывает.
Даже когда free() может технически вернуть память в ОС, он может этого не сделать. free() необходимо достичь баланса между быстрой работой и экономией памяти. Кроме того, программа, которая уже выделила много памяти, а затем освободила ее, скорее всего, сделает это снова. Веб-серверу необходимо обрабатывать запрос за запросом за запросом - имеет смысл оставить некоторую «свободную» память доступной, чтобы вам не приходилось постоянно запрашивать память у ОС.
Что, если другим программам требуется память, которую ваша программа удерживает излишне, поэтому, даже если вам больше не нужны маллоки, free () неиспользуемые области памяти :)
Вы полностью упустили мою точку зрения. Когда вы освобождаете () память, другие программы не могут ее использовать !! (Иногда они могут, особенно если вы освобождаете большие блоки памяти. Но часто они не могут!) Я отредактирую свой пост, чтобы прояснить это.
Как правило, если у вас есть утечки памяти, которых вы не можете избежать, вам нужно больше подумать о владении объектами.
Но на ваш вопрос я кратко отвечу В производственном коде - да. Во время разработки нет. Это может показаться обратным, но вот мои рассуждения:
В описанной вами ситуации, когда память удерживается до конца программы, совершенно нормально не освобождать ее. Как только ваш процесс завершится, ОС все равно очистится. Фактически, это могло бы улучшить взаимодействие с пользователем: в игре, над которой я работал, программисты думали, что было бы чище освободить всю память перед выходом, в результате чего завершение работы программы заняло до получаса! Быстрое изменение, которое просто вызвало exit (), заставило процесс немедленно исчезнуть и вернуть пользователя на рабочий стол, где он хотел быть.
Тем не менее, вы правы насчет инструментов отладки: они вызовут истерику, и все ложные срабатывания могут сделать обнаружение ваших реальных утечек памяти проблемой. И поэтому всегда пишите отладочный код, который освобождает память, и отключайте его при отправке.
Это действительно зависит от использования объекта, создающего утечку памяти. Если вы создаете объект столько раз за время существования приложения, которое использует этот объект, то использовать такой способ - плохо. Потому что будет очень много утечки памяти. С другой стороны, если у нас есть единственный экземпляр объекта без использования памяти и утечки только небольшого количества, это не проблема.
Утечка памяти представляет собой проблему, когда утечка увеличивается во время работы приложения.
Пока использование вашей памяти не увеличивается со временем, это зависит. Если вы выполняете много сложной синхронизации в серверном программном обеспечении, например, запускаете фоновые потоки, которые блокируют системные вызовы, выполнение чистого выключения может быть слишком сложным, чтобы его можно было оправдать. В этой ситуации альтернативы могут быть:
Нет, у вас не должно быть утечек, которые ОС очистит за вас. Причина (не упомянутая в ответах выше, насколько я мог проверить) в том, что вы никогда не знаете когда ваш main () будет повторно использоваться как функция / модуль в другой программе. Если ваша main () станет часто вызываемой функцией в программном обеспечении других лиц - в этом программном обеспечении будет утечка памяти, которая со временем съедает память.
KIV
Когда приложение завершает работу, можно утверждать, что лучше не освобождать память.
Теоретически ОС должна освобождать ресурсы, используемые приложением, но всегда есть ресурсы, которые являются исключениями из этого правила. Так что будьте осторожны.
Преимущество простого выхода из приложения:
Плохая ситуация с выходом состоит из двух моментов:
Из-за этого вам может потребоваться два режима завершения работы: один быстрый и грязный для конечных пользователей, а другой медленный и тщательный для разработчиков. Только не забудьте протестировать оба :)
Только в одном случае: программа собирается выстрелить из-за неисправимой ошибки.
Лучшая практика - всегда освобождать то, что вы выделяете, особенно если вы пишете что-то, что предназначено для работы в течение всего времени безотказной работы системы, даже при очистке перед выходом.
Это очень простое правило ... программирование с целью исключения утечек позволяет легко обнаружить новые утечки. Вы бы продали кому-нибудь машину, которую сделали, зная, что она разбрызгивает газ на землю каждый раз, когда ее выключают? :)
Несколько вызовов if () free () в функции очистки дешевы, почему бы их не использовать?
В то время как большинство ответов сосредоточены на реальных утечках памяти (что никогда не бывает нормально, потому что они являются признаком небрежного кодирования), эта часть вопроса кажется мне более интересной:
What if you allocate some memory and use it until the very last line of code in your application (for example, a global object's deconstructor)? As long as the memory consumption doesn't grow over time, is it OK to trust the OS to free your memory for you when your application terminates (on Windows, Mac, and Linux)? Would you even consider this a real memory leak if the memory was being used continuously until it was freed by the OS.
Если связанная память используется, вы не можете освободить ее до завершения программы. Выполняется ли освобождение при выходе из программы или ОС, не имеет значения. Пока это задокументировано, чтобы это изменение не приводило к реальным утечкам памяти, и пока в изображении не задействован деструктор C++ или функция очистки C. Незакрытый файл может быть обнаружен через просочившийся объект FILE, но отсутствие функции fclose () также может привести к тому, что буфер не будет очищен.
Итак, возвращаясь к исходному случаю, ИМХО это совершенно нормально само по себе, настолько, что Valgrind, один из самых мощных детекторов утечек, будет обрабатывать такие утечки только по запросу. В Valgrind, когда вы перезаписываете указатель, не освобождая его заранее, это считается утечкой памяти, потому что с большей вероятностью это произойдет снова и вызовет бесконечный рост кучи.
Тогда нет свободных блоков памяти, которые все еще доступны. Можно было бы обязательно освободить их всех на выходе, но это само по себе пустая трата времени. Дело в том, можно ли их освободить до. Снижение потребления памяти полезно в любом случае.
Вау ... кто-то знает, что такое утечка памяти.
Если вы используете его до конца вашего main(), это просто не утечка (конечно, при наличии защищенной системы памяти!).
Фактически, освобождение объектов при завершении процесса - это абсолютная худший вещь, которую вы могли бы сделать ... ОС должна вернуться назад в каждая страница, которую вы когда-либо создавали. Закройте дескрипторы файлов, соединения с базой данных, конечно, но освобождать память - это глупо.
Если в вашем коде есть утечки памяти, даже известные «приемлемые» утечки, вам будет неприятно использовать любые инструменты утечки памяти, чтобы найти свои «настоящие» утечки. Точно так же, как оставление «приемлемых» предупреждений компилятора затрудняет поиск новых, «настоящих» предупреждений.
Нет, они не в порядке, но я реализовал несколько распределителей, дамперов памяти и детекторов утечек и обнаружил, что с практической точки зрения удобно разрешить помечать такое распределение как "Не утечка, что касается отчета об утечках" ...
Это помогает сделать отчет об утечке более полезным ... и не переполненным «динамическим распределением в статической области, не освобождаемым при выходе из программы»
Возможно, косяк: что, если ваше приложение работает в UNIX и может стать зомби? В этом случае операционная система не использует память. Поэтому я говорю, что вам действительно следует освободить память перед выходом из программы.
Совершенно приемлемо опустить освобождение памяти в последней строке программы, поскольку ее освобождение ни на что не повлияет, поскольку программе больше никогда не понадобится память.
Я считаю, что это нормально, если у вас есть программа, которая запускается в течение нескольких секунд, а затем закрывается и предназначена только для личного использования. Любые утечки памяти будут устранены, как только ваша программа завершится.
Проблема возникает, когда у вас есть программа, которая работает долгое время, и пользователи полагаются на нее. Также это плохая привычка кодирования допускать утечки памяти в вашей программе, особенно для работы, если они могут когда-нибудь превратить этот код во что-то еще.
В общем, утечки памяти лучше устранить.
Я взял один класс в старшей школе на C, и учитель сказал, что всегда нужно освобождать, когда вы malloc.
Но когда я поступил в колледж еще на один курс, профессор сказал, что нельзя бесплатно использовать небольшие программы, которые выполняются только на секунду. Так что я полагаю, что это не повредит вашей программе, но это хорошая практика - освободить надежный и здоровый код.
Я дам непопулярный, но практичный ответ, что это всегда неправильно освобождать память, если это не уменьшит использование памяти вашей программой. Например, программе, которая выполняет одно или несколько распределений для загрузки набора данных, который она будет использовать в течение всего своего жизненного цикла, не нужно ничего освобождать. В более распространенном случае большой программы с очень динамическими требованиями к памяти (подумайте о веб-браузере), вы должны, очевидно, освободить память, которую вы больше не используете, как только сможете (например, закрыв вкладку / документ / и т. д.). , но нет никаких причин освобождать что-либо, когда пользователь нажимает кнопку «Выход», и это действительно вредно для взаимодействия с пользователем.
Почему? Освобождение памяти требует прикосновения к памяти. Даже если ваша системная реализация malloc не хранит метаданные рядом с выделенными блоками памяти, вы, вероятно, будете ходить по рекурсивным структурам только для того, чтобы найти все указатели, которые вам нужно освободить.
Теперь предположим, что ваша программа работала с большим объемом данных, но какое-то время не обрабатывала большую их часть (опять же, веб-браузер - отличный пример). Если пользователь запускает много приложений, значительная часть этих данных, вероятно, была перенесена на диск. Если вы просто выйдете (0) или вернетесь из main, он немедленно завершится. Отличный пользовательский опыт. Если вы попытаетесь освободить все, вы можете потратить 5 секунд или более на то, чтобы вернуть все данные обратно, а сразу после этого выбросить их. Пустая трата времени пользователя. Пустая трата времени автономной работы ноутбука. Отходы износа жесткого диска.
Это не только теоретически. Всякий раз, когда я обнаруживаю, что загружено слишком много приложений и диск начинает перегружаться, я даже не думаю о нажатии кнопки «Выход». Я добираюсь до терминала так быстро, как могу, и набираю killall -9 ... потому что знаю, что "exit" только усугубит ситуацию.
Мне очень нравится эта цитата Раймонда Чена: «Здание сносят. Не беспокойтесь о подметании пола, опорожнении мусорных баков и стирании досок. И не выстраивайтесь в очередь у выхода из здания, чтобы каждый мог переместиться внутрь. из магнита наружу. Все, что вы делаете, заставляете команду по сносу ждать, пока вы закончите эти бессмысленные работы по уборке дома ". (blogs.msdn.microsoft.com/oldnewthing/20120105-00/?p=8683)
Некоторое время назад я бы сказал да, что когда-то было приемлемо допустить утечку памяти в вашей программе (она все еще находится на стадии быстрого прототипирования), но, сделав сейчас в 5 или 6 раз больше опыта, отслеживание даже малейшей утечки выявило некоторые действительно серьезные функциональные ошибки. Допуск утечки в программе происходит, когда жизненный цикл объекта данных на самом деле неизвестен, что свидетельствует о полном отсутствии анализа. Итак, в заключение, всегда полезно знать, что происходит в программе.
Подумайте о случае, когда приложение позже используется из другого, с возможностью открывать несколько из них в отдельных окнах или одно за другим для выполнения каких-либо действий. Если он запускается не как процесс, а как библиотека, то вызывающая программа дает утечку памяти, потому что вы думали, что пропустите очистку памяти.
Используйте какой-то умный указатель, который сделает это за вас автоматически (например, scoped_ptr из Boost libs)
Я думаю, это нормально, если вы пишете программу, предназначенную для утечки памяти (т.е. для проверки влияния утечек памяти на производительность системы).
Правило простое: если вы закончили использовать какую-то память, очистите ее. а иногда, даже если нам понадобятся несколько экземпляров позже, но мы отмечаем, что мы сильно используем память, поэтому это может повлиять на производительность из-за подкачки на диск, мы можем хранить данные в файлах на диске и после их перезагрузки, иногда этот метод значительно оптимизирует вашу программу .
I only see one practical disadvantage, and that is that these benign leaks will show up with memory leak detection tools as false positives.
Если я правильно понял, вы явно не освобождаете память (которую можно освободить, потому что у вас все еще есть указатель) и полагаетесь на ОС, чтобы освободить ее во время завершения процесса. Хотя это может показаться нормальным для простой программы, рассмотрим ситуацию, когда ваш код перемещается в библиотеку и становится частью некоторого резидентного процесса демона, работающего круглосуточно и без выходных. Скажем, этот демон порождает поток каждый раз, когда ему нужно сделать что-то полезное с использованием вашего кода, и скажем, что он порождает тысячи потоков каждый час. В этом случае вы получите утечку памяти настоящий.
К сожалению, в реальной жизни такая ситуация вполне вероятна, и последовательные методы управления памятью могут облегчить вам жизнь.
Я удивлен, увидев так много неверных определений того, что на самом деле представляет собой утечка памяти. Без конкретного определения дискуссия о том, плохо это или нет, ни к чему не приведет.
Как справедливо отметили некоторые комментаторы, утечка памяти происходит только тогда, когда память, выделенная процессом, выходит за рамки до такой степени, что процесс больше не может ссылаться на нее или удалять ее.
Процесс, который захватывает все больше и больше памяти, не обязательно протекает. Пока он может ссылаться на эту память и освобождать ее, она остается под явным контролем процесса и не имеет утечки. Процесс вполне может быть плохо спроектирован, особенно в контексте системы с ограниченным объемом памяти, но это не то же самое, что утечка. И наоборот, потеря объема, скажем, 32-байтового буфера все еще является утечкой, даже если объем утечки памяти невелик. Если вы думаете, что это несущественно, подождите, пока кто-нибудь не обернет алгоритм вокруг вашего библиотечного вызова и не вызовет его 10 000 раз.
Я не вижу никаких причин допускать утечки в вашем собственном коде, даже небольшие. Современные языки программирования, такие как C и C++, делают все возможное, чтобы помочь программистам предотвратить такие утечки, и редко есть веский аргумент не применять хорошие методы программирования - особенно в сочетании с конкретными языковыми средствами - для предотвращения утечек.
Что касается существующего или стороннего кода, где ваш контроль качества или возможность вносить изменения могут быть сильно ограничены, в зависимости от серьезности утечки вы можете быть вынуждены принять или предпринять смягчающие меры, такие как регулярный перезапуск вашего процесса для уменьшения эффект утечки.
Возможно, невозможно изменить или заменить существующий (текущий) код, и поэтому вы можете быть обязаны его принять. Однако это не то же самое, что заявлять, что все в порядке.
Да, утечка памяти может быть меньшим из двух зол. Хотя правильность важна, производительность или стабильность системы могут быть затронуты при выполнении полного освобождения памяти, а риски и время, затрачиваемое на освобождение памяти и уничтожение объектов, могут быть менее желательными, чем простой выход из процесса.
Как правило, оставлять воспоминания неприемлемо. Трудно понять все области, в которых будет выполняться ваш код, и в некоторых случаях это может привести к тому, что утечка станет катастрофической.
What if you allocate some memory and use it until the very last line of code in your application (for example, a global object's destructor)?
В этом случае ваш код может быть перенесен в более крупный проект. Это может означать, что время жизни вашего объекта слишком велико (оно длится для всей программы, а не только для экземпляра, в котором он нужен), или что если глобальный объект будет создан и уничтожен, произойдет утечка.
is it OK to trust the OS to free your memory for you when your application terminates
Когда короткоживущая программа создает большие коллекции C++ (например, std::map), на каждый объект приходится как минимум 2 выделения. Итерация по этой коллекции для уничтожения объектов требует реального времени для ЦП, а оставление объекта для утечки и очистки ОС дает преимущества в производительности. Счетчик, есть ли некоторые ресурсы, которые не приводятся в порядок ОС (например, общая память), и не уничтожение всех объектов в вашем коде создает риск того, что некоторые из них удерживаются на этих несвободных ресурсах.
What if a third party library forced this situation on you?
Во-первых, я бы поднял ошибку для функции close, которая освобождает ресурсы. Вопрос о том, приемлемо ли это, основывается на том, какие преимущества предлагает библиотека (стоимость, производительность, надежность), лучше, чем делать это с какой-либо другой библиотекой или писать ее самостоятельно.
В общем, если бы библиотека не была повторно инициализирована, я бы, вероятно, не беспокоился.
Если операционная система будет выключена, все ресурсы будут приведены в порядок. Преимущество невыполнения нормального завершения процесса заключается в том, что пользователь получает более высокую производительность при выключении.
В моем прошлом мы нашли объект (и вызвали дефект для этой команды), что если они разбиваются в определенных точках, они становятся сломанными, и все последующие функции в этом объекте приводят к зависанию.
Несмотря на то, что игнорировать утечку памяти - плохая практика, более продуктивно было завершить работу нашего процесса, вызвав утечку объекта и его памяти, чем приводить к зависанию.
Некоторые средства проверки утечек работают с объектами и ведут себя так же, как глобальные объекты. Иногда они могут пропустить, что у другого глобального объекта есть действующий деструктор, вызываемый после завершения, который освободит память.
В ответах, похоже, не учитывается то, что инициализация жесткая и так это уборка. Конечно, это может быть оправдано с учетом будущих требований, но за это придется заплатить. Незавершенное завершение работы создает новые промежуточные состояния, требующие осторожного обращения, в противном случае вызывая скачки и другие ошибки. Рассмотрите возможность деинициализации приложения, разделенного на пользовательский интерфейс и рабочий поток, и необходимости обработки для другого конца, который больше не существует. По моему опыту программирования встраиваемых систем с нуля, никто не беспокоится о выключении периферийных устройств и освобождении памяти во время отключения питания, за исключением случаев, когда это требуется для правильности.
Другими словами, решение не убирать за собой там, где это считается ненужным, может быть не столько признаком лени, сколько инженерным компромиссом.
Здесь есть отличные ответы. Чтобы добавить другую перспективу к этому вопросу, я обращусь к случаю, когда утечка памяти не только приемлемо, но и желательно: в среде драйверов Windows разработчик предоставляет набор обратных вызовов, которые запускаются ОС по мере необходимости. Один из обратных вызовов - это обратный вызов «Завершение работы», который выполняется до отключения / перезапуска системы. В отличие от стандартных ситуаций, не только освобождение памяти не требуется (система отключится через мгновение), но даже не рекомендуется - чтобы завершить работу как можно быстрее и предотвратить накладные расходы на управление памятью.
Если потребление памяти не растет со временем, это не утечка.