Утечки памяти когда-либо в порядке?

Приемлемо ли когда-либо иметь утечку памяти в вашем приложении C или C++?

Что если вы выделите немного памяти и будете использовать ее до самой последней строки кода в вашем приложении (например, деструктор глобального объекта)? Пока потребление памяти не увеличивается со временем, можно ли доверять ОС освободить вашу память для вас после завершения работы приложения (в Windows, Mac и Linux)? Считаете ли вы это настоящей утечкой памяти, если память использовалась непрерывно, пока она не была освобождена ОС.

Что если сторонняя библиотека навязывает вам такую ​​ситуацию? Отказался бы от использования сторонней библиотеки, какой бы великой она ни была?

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

50 ответов

Решение

Нет.

Как профессионалы, вопрос, который мы не должны задавать себе: "Это когда-нибудь нормально делать?" а скорее "Есть ли когда-нибудь веская причина для этого?" И "выслеживание утечки памяти - это боль" - не веская причина.

Мне нравится, чтобы все было просто. И простое правило: у моей программы не должно быть утечек памяти.

Это тоже делает мою жизнь проще. Если я обнаруживаю утечку памяти, я устраняю ее, а не прохожу через сложную структуру дерева решений, чтобы определить, является ли она "приемлемой" утечкой памяти.

Это похоже на предупреждения компилятора - будет ли это фатальным для моего конкретного приложения? Возможно, нет.

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

Чтобы довести дело до крайности, будет ли когда-нибудь хирургом оставлять какой-либо предмет операционного оборудования внутри пациента?

Хотя вполне возможно, что может возникнуть обстоятельство, когда стоимость / риск удаления этого элемента оборудования превышает стоимость / риск его оставления в нем, и могут быть обстоятельства, когда оно было безвредным, если бы я увидел этот вопрос, размещенный на SurgeonOverflow.com и видел любой ответ, кроме "нет", это серьезно подорвало бы мою уверенность в медицинской профессии.

-

Если бы сторонняя библиотека навязывала мне такую ​​ситуацию, это заставило бы меня серьезно подозревать общее качество рассматриваемой библиотеки. Это было бы так, как если бы я тестировал за рулем автомобиля и обнаружил пару незакрепленных шайб и гаек в одном из подстаканников - само по себе это может не иметь большого значения, но это свидетельствует об отсутствии приверженности качеству, поэтому я бы рассмотрел альтернативы.

Я не считаю, что это утечка памяти, если объем используемой памяти не увеличивается. Наличие некоторой невыпущенной памяти, хотя и не идеальной, не является большой проблемой, если только объем необходимой памяти не увеличивается.

Давайте сначала получим правильные определения. Утечка памяти - это когда память выделяется динамически, например, с malloc()и все ссылки на память теряются без соответствующей свободной. Простой способ сделать это так:

#define BLK ((size_t)1024)
while(1){
    void * vp = malloc(BLK);
}

Обратите внимание, что каждый раз вокруг цикла while(1) выделяется 1024 (+ служебные) байта, а новый адрес назначается для vp; нет остающегося указателя на предыдущие блоки malloc. Эта программа гарантированно будет работать до тех пор, пока не закончится куча, и нет никакого способа восстановить память, выделенную из памяти. Память "просачивается" из кучи, и больше никогда ее не увидеть.

То, что вы описываете, звучит как

int main(){
    void * vp = malloc(LOTS);
    // Go do something useful
    return 0;
}

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

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

В теории нет, на практике это зависит.

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

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

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

Что касается сторонних библиотек, у которых есть утечки, если они вызывают проблему, или исправьте библиотеку или найдите лучшую альтернативу. Если это не вызывает проблемы, действительно ли это имеет значение?

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

Это не правда Операционные системы обычно управляют памятью в страницах 4KiB. malloc и другие виды управления памятью получают страницы из ОС и управляют ими по своему усмотрению. Вполне вероятно, что free() не будет возвращать страницы в операционную систему, при условии, что ваша программа будет выделять больше памяти позже.

Я не говорю что free() никогда не возвращает память операционной системе. Это может произойти, особенно если вы освобождаете большие участки памяти. Но нет гарантии.

Важный факт: если вы не освобождаете память, которая вам больше не нужна, дальнейшие malloc гарантированно потребляют еще больше памяти. Но если вы сначала освободитесь, то вместо этого malloc может повторно использовать освобожденную память.

Что это значит на практике? Это означает, что если вы знаете, что вашей программе больше не требуется больше памяти (например, она находится на этапе очистки), освобождение памяти не так важно. Однако, если программа может выделить больше памяти позже, вам следует избегать утечек памяти - особенно тех, которые могут повторяться.

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

Комментатор, похоже, не понимает, что зовет free() не позволяет автоматически другим программам использовать освобожденную память. Но в этом весь смысл этого ответа!

Итак, чтобы убедить людей, я продемонстрирую пример, в котором free() приносит мало пользы. Чтобы упростить математику, я сделаю вид, что ОС управляет памятью в 4000 байтовых страниц.

Предположим, вы выделяете десять тысяч 100-байтовых блоков (для простоты я буду игнорировать дополнительную память, которая потребуется для управления этими выделениями). Это занимает 1 МБ или 250 страниц. Если вы затем освободите 9000 из этих блоков наугад, у вас останется всего 1000 блоков - но они разбросаны повсюду. По статистике, около 5 страниц будут пустыми. Каждый из остальных 245 будет иметь по меньшей мере один выделенный блок. Это составляет 980 КБ памяти, которая не может быть восстановлена ​​операционной системой - даже если теперь у вас есть только 100 КБ!

С другой стороны, теперь вы можете malloc() на 9000 блоков больше, не увеличивая объем памяти, который связывает ваша программа.

Даже когда free() технически может вернуть память в ОС, это может не произойти. free() Необходимо достичь баланса между быстрой работой и экономией памяти. Кроме того, программа, которая уже выделила много памяти, а затем освободила ее, вероятно, сделает это снова. Веб-сервер должен обрабатывать запрос за запросом после запроса - имеет смысл сохранять некоторую "свободную" память доступной, чтобы вам не приходилось постоянно запрашивать память у ОС.

В принципе нет ничего плохого в том, чтобы очистить ОС после запуска приложения.

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

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

Я считаю, что ответ "нет", никогда не допускайте утечки памяти, и у меня есть несколько причин, которые я не видел в явном виде. Здесь есть отличные технические ответы, но я думаю, что реальный ответ зависит от социальных / человеческих причин.

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

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

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

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

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

Есть и более социальный аспект. При правильном использовании malloc() а также free()любому, кто смотрит на ваш код, будет легко; Вы управляете своими ресурсами. Если вы этого не сделаете, они сразу заподозрят проблему.

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

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

Умное программирование является гибким и общим. Плохое программирование неоднозначно.

Я собираюсь дать непопулярный, но практичный ответ, что освобождать память всегда неправильно, если это не уменьшит использование памяти вашей программой. Например, программе, которая делает одно выделение или серию выделений для загрузки набора данных, который она будет использовать в течение всего времени своего существования, не нужно ничего освобождать. В более распространенном случае большой программы с очень динамическими требованиями к памяти (например, веб-браузер) вам, очевидно, следует освободить память, которую вы больше не используете, как можно скорее (например, закрыть вкладку / документ / и т. Д.), но нет никакой причины освобождать что-либо, когда пользователь выбирает щелчок "выход", и это на самом деле вредно для пользователя.

Зачем? Освобождение памяти требует прикосновения к памяти. Даже если реализация malloc вашей системы не хранит метаданные рядом с выделенными блоками памяти, вы, скорее всего, будете ходить по рекурсивным структурам, просто чтобы найти все указатели, которые вам нужно освободить.

Теперь предположим, что ваша программа работала с большим объемом данных, но некоторое время не затрагивала большую их часть (опять же, веб-браузер - отличный пример). Если пользователь запускает много приложений, значительная часть этих данных, вероятно, была перенесена на диск. Если вы просто выйдите из (0) или вернетесь из основного, он выйдет мгновенно. Отличный пользовательский опыт. Если вы попытаетесь освободить все, вы можете потратить 5 или более секунд, чтобы обменять все данные обратно, только чтобы сразу выбросить их. Трата времени пользователя. Потеря времени работы ноутбука от батареи. Отходы износа на жестком диске.

Это не просто теоретическое. Всякий раз, когда я обнаруживаю, что загружено слишком много приложений, и диск начинает трепетать, я даже не думаю о нажатии "Выход". Я добираюсь до терминала так быстро, как могу, и набираю killall -9 ... потому что я знаю, что "выход" только ухудшит ситуацию.

Я думаю, что в вашей ситуации ответ может быть, что все в порядке. Но вам определенно необходимо документально подтвердить, что утечка памяти является сознательным решением. Вы не хотите, чтобы программист по обслуживанию приходил, вставлял свой код в функцию и вызывал ее миллион раз. Поэтому, если вы примете решение, что утечка в порядке, вам нужно ее документировать (В БОЛЬШИХ БУКВАХ) для тех, кому, возможно, придется работать над программой в будущем.

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

Но в основном, если утечка памяти - это известная величина, такая как буфер 512 КБ или что-то еще, это не проблема. Если утечка памяти продолжает расти, как при каждом вызове библиотеки, ваша память увеличивается на 512 КБ и не освобождается, тогда у вас могут быть проблемы. Если вы задокументируете это и проконтролируете, сколько раз вызов будет выполнен, это может быть управляемым. Но тогда вам действительно нужна документация, потому что, хотя 512 не много, 512 более миллиона звонков - это много.

Также вам необходимо проверить документацию вашей операционной системы. Если это было встроенное устройство, возможно, существуют операционные системы, которые не освобождают всю память из программы, которая выходит. Я не уверен, может быть, это не так. Но это стоит посмотреть.

Я уверен, что кто-то может найти причину, чтобы сказать Да, но это не я. Вместо того, чтобы говорить "нет", я собираюсь сказать, что это не должно быть вопросом "да / нет". Существуют способы управления или устранения утечек памяти, и во многих системах они есть.

Существуют системы НАСА на устройствах, которые покидают Землю, которые планируют это. Системы будут автоматически перезагружаться, так что утечки памяти не станут фатальными для всей работы. Просто пример сдерживания.

Я могу рассчитывать с одной стороны на количество "доброкачественных" утечек, которые я видел со временем.

Так что ответ очень квалифицированный да.

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

Я видел, что этот подход приносил большую пользу для вещей с очень четко фиксированными подсчетами, такими как запросы на кражу работы на процессор, и в гораздо меньшей степени в буфере, используемом для хранения синглтона. /proc/self/maps состояние в консервативном сборщике мусора Ханса Бома для C/C++, который используется для обнаружения корневых наборов и т. д.

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

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

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

На самом деле, нет необходимости совершать вызовы free() или удалять прямо перед выходом. Когда процесс завершается, ОС освобождает всю его память (это, безусловно, имеет место в POSIX. В других ОС - особенно встраиваемых - YMMV).

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

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

  • операционная система космического челнока: нет, утечки памяти не допускаются
  • быстрая разработка кода для проверки концепции: устранение всех этих утечек памяти - пустая трата времени.

и есть спектр промежуточных ситуаций.

альтернативная стоимость ($$$) задержки выпуска продукта, чтобы устранить все, кроме самых серьезных утечек памяти, обычно затмевает любое чувство "неряшливости или непрофессионализма". Твой начальник платит тебе, чтобы он зарабатывал ему деньги, а не получал теплые, нечеткие чувства.

В такого рода вопросах контекст - это все. Лично я терпеть не могу утечки, и в своем коде я прилагаю все усилия, чтобы исправить их, если они возникнут, но не всегда стоит исправлять утечку, и когда люди платят мне по часам, которые я иногда сказал им, что не стоит платить мне за исправление утечки в их коде. Позволь мне привести пример:

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

Лично я не написал бы код таким образом, во-первых, но большинство из нас не всегда работают над нетронутыми хорошо разработанными базами кода, и иногда вам приходится смотреть на эти вещи прагматично. Время, которое потребовалось бы мне, чтобы исправить утечку в 150 байт, вместо этого могло быть потрачено на усовершенствование алгоритмов, которое сократило мегабайты оперативной памяти.

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

Сначала вы должны понять, что существует большая разница между видимой утечкой памяти и реальной утечкой памяти. Очень часто аналитические инструменты сообщают о множестве красных шедевров и помечают что-то как утечку (память или ресурсы, такие как дескрипторы и т. Д.) Там, где это на самом деле нет. Часто это происходит из-за архитектуры инструмента анализа. Например, некоторые инструменты анализа сообщают об объектах времени выполнения как об утечках памяти, потому что они никогда не видят эти объекты свободными. Но освобождение происходит в коде завершения среды выполнения, который инструмент анализа может не увидеть.

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

Идеальный ответ: "Нет, никогда". Более прагматичный ответ может быть "нет, почти никогда". Очень часто в реальной жизни у вас ограниченное количество ресурсов и времени для решения и бесконечный список задач. Когда одной из задач является устранение утечек памяти, очень часто вступает в действие закон убывающей отдачи. Вы можете устранить, скажем, 98% всех утечек памяти в приложении за неделю, но оставшиеся 2% могут занять месяцы. В некоторых случаях может быть даже невозможно устранить некоторые утечки из-за архитектуры приложения без серьезного рефакторинга кода. Вы должны взвесить затраты и выгоды от устранения оставшихся 2%.

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

Что если вы выделите некоторую память и будете использовать ее до самой последней строки кода в вашем приложении (например, для деконструктора глобального объекта)? Пока потребление памяти не растет со временем, можно ли доверять ОС освободить вашу память для вас, когда ваше приложение завершает работу (в Windows, Mac и Linux)? Считаете ли вы это настоящей утечкой памяти, если память использовалась непрерывно, пока она не была освобождена ОС.

Если используется связанная память, вы не можете ее освободить до завершения программы. Независимо от того, делается ли это бесплатно при выходе из программы или ОС. Пока это задокументировано, чтобы изменения не приводили к реальным утечкам памяти, и до тех пор, пока в картине нет деструктора C++ или функции очистки C. Незакрытый файл может быть обнаружен через утечку FILE объект, но отсутствующий fclose() также может привести к тому, что буфер не будет очищен.

Итак, вернемся к исходному случаю. ИМХО само по себе совершенно нормально, настолько, что Valgrind, один из самых мощных детекторов утечек, будет обрабатывать такие утечки только по запросу. На Valgrind, когда вы перезаписываете указатель, не освобождая его заранее, это рассматривается как утечка памяти, потому что с большей вероятностью это произойдет снова и приведет к бесконечному росту кучи.

Кроме того, нет свободных блоков памяти, которые все еще доступны. Можно было освободить их всех на выходе, но это пустая трата времени сама по себе. Дело в том, если бы они могли быть освобождены раньше. Снижение потребления памяти полезно в любом случае.

Нет, у вас не должно быть утечек, которые ОС очистит для вас. Причина (не упомянутая в ответах выше, насколько я мог проверить) заключается в том, что вы никогда не знаете, когда ваш main() будет повторно использован в качестве функции / модуля в другой программе. Если ваш main() становится часто вызываемой функцией в программном обеспечении других лиц - это программное обеспечение будет иметь утечку памяти, которая со временем истощает память.

KIV

Я согласен с vfilby - это зависит. В Windows мы рассматриваем утечки памяти как относительно серьезные ошибки. Но это очень сильно зависит от компонента.

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

Тем не менее, утечки памяти в службах или других долгосрочных компонентах (таких как оболочка) очень серьезны. Причина в том, что эти ошибки со временем "крадут" память. Единственный способ восстановить это - перезапустить компоненты. Большинство людей не знают, как перезапустить службу или оболочку - поэтому, если их производительность системы страдает, они просто перезагружаются.

Итак, если у вас есть утечка - оцените ее влияние двумя способами

  1. К вашему программному обеспечению и опыту вашего пользователя.
  2. Для системы (и пользователя) с точки зрения экономии ресурсов системы.
  3. Влияние исправления на техническое обслуживание и надежность.
  4. Вероятность возникновения регрессии в другом месте.

Foredecker

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

Для меня задавать вопросы - это все равно что задавать вопросы "Могу ли я выключить красный свет в 3 часа ночи, когда никого нет рядом?". Ну, конечно, это может не вызвать никаких проблем в это время, но это даст вам рычаг, чтобы сделать то же самое в час пик!

Я удивлен, увидев так много неверных определений того, что на самом деле является утечка памяти. Без конкретного определения, дискуссия о том, плохо это или нет, ни к чему не приведет.

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

Процесс, который захватывает все больше и больше памяти, не обязательно протекает. Пока он может ссылаться и освобождать эту память, он остается под явным контролем процесса и не просочился. Процесс может быть плохо спроектирован, особенно в контексте системы, где память ограничена, но это не то же самое, что утечка. И наоборот, потеря объема, скажем, 32-байтового буфера все еще является утечкой, даже если утечка памяти мала. Если вы считаете, что это несущественно, подождите, пока кто-нибудь не обернет алгоритм вокруг вашего библиотечного вызова и вызовет его 10000 раз.

Я не вижу причин, чтобы допускать утечки в вашем собственном коде, какими бы маленькими они ни были. Современные языки программирования, такие как C и C++, делают все возможное, чтобы помочь программистам предотвратить такие утечки, и редко бывают веские аргументы в пользу того, чтобы не применять хорошие методы программирования - особенно в сочетании с конкретными языковыми средствами - для предотвращения утечек.

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

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

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

Да, утечка памяти может быть меньшим из двух зол. Хотя правильность важна, производительность или стабильность системы могут быть затронуты при выполнении полного освобождения памяти, а риски и время, затрачиваемое на освобождение памяти и уничтожение объектов, могут быть менее желательными, чем просто выход из процесса.

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

Что если вы выделите немного памяти и будете использовать ее до самой последней строки кода в вашем приложении (например, деструктор глобального объекта)?

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

Можно ли доверять ОС, чтобы освободить память для вас после завершения работы приложения?

Когда недолговечная программа создает большие C++ коллекции (например, std::map), по крайней мере, 2 выделения на объект. Итерация по этой коллекции для уничтожения объектов требует реального времени для ЦП, а оставление объекта для утечки и очистки операционной системой имеет преимущества в производительности. Счетчик в том, что есть некоторые ресурсы, которые не убираются ОС (например, разделяемая память), и не уничтожение всех объектов в вашем коде открывает риск, что некоторые хранятся в этих неосвобожденных ресурсах.

Что если сторонняя библиотека навязывает вам такую ​​ситуацию?

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

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

приемлемое время для сообщения об утечке памяти.

  1. Служба во время выключения. Здесь есть компромисс между временем выполнения и правильностью.
  2. Сломанный предмет, который нельзя уничтожить. Мне удалось обнаружить сбойный объект (например, из-за перехвата исключения), и когда я пытаюсь уничтожить объект, результатом является зависание (удерживаемая блокировка).
  3. Ошибка проверки памяти.

Служба во время выключения

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

Сломанный предмет

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

Хотя игнорирование утечек памяти является плохой практикой, было бы более продуктивно остановить наш процесс, вытекший объект и его память, чем привести к зависанию.

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

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

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

Что вы делаете для серверных программ, которые разработаны так, чтобы они не закрывались?

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

Утечка памяти и позволить программе очистить его? Абсолютно нет. Это плохая привычка, которая приводит к ошибкам, ошибкам и другим ошибкам.

Убери за собой. Эй, мама, не работай здесь больше нет.

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

Я отвечу нет.

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

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

Это уже обсуждалось до тошноты. Суть в том, что утечка памяти является ошибкой и должна быть исправлена. Если у сторонней библиотеки утечка памяти, возникает вопрос: а что с ней не так? Если бы вы строили автомобиль, вы бы использовали двигатель, в котором иногда течет масло? В конце концов, кто-то другой сделал двигатель, так что это не твоя вина, и ты не можешь это исправить, верно?

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

Но на ваш вопрос мой ответ в двух словах: " В рабочем коде", да. Во время разработки нет. Это может показаться задом наперед, но вот мои рассуждения:

В описанной вами ситуации, когда память хранится до конца программы, вполне нормально не освобождать ее. Как только ваш процесс завершится, ОС все равно очистится. На самом деле, это может улучшить восприятие пользователя: в игре, над которой я работал, программисты подумали, что было бы чище освободить всю память перед выходом, в результате чего остановка программы займет до полуминуты! Быстрое изменение, которое вызывается только методом exit(), сразу же приводит к тому, что процесс сразу исчезает, и пользователь возвращается на рабочий стол, где он и хотел быть.

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

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

Если я правильно понял, вы явно не освобождаете память (которую можно освободить, потому что у вас все еще есть указатель) и полагаетесь на ОС, чтобы освободить ее во время завершения процесса. Хотя это может показаться нормальным для простой программы, рассмотрим ситуацию, когда ваш код перемещается в библиотеку и становится частью некоторого резидентного процесса демона, работающего 24/7. Скажем, этот демон порождает поток каждый раз, когда ему нужно сделать что-то полезное, используя ваш код, и скажите, что он порождает тысячи потоков каждый час. В этом случае вы получите реальную утечку памяти.

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

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

Другие вопросы по тегам