Допустимо ли освобождать память

Я работаю над проектом, который предполагается использовать из командной строки со следующим синтаксисом:

program-name input-file

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

Мой язык выбора - С++ по нескольким причинам, которые я не хочу обсуждать. Фаза вычисления будет очень символичной (думаю, компилятор) и будет использовать довольно сложные динамически распределенные структуры данных. В частности, это не поддается программированию стиля RAII.

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

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

Ответ 1

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

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

Ответ 2

Иногда не освобождать память - это правильная вещь.

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

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

НТН! FWIW, это было "в тот же день", когда память была не виртуальной и минимальной, ящики были намного медленнее, а первые два были нетривиальными соображениями.

Ответ 3

Мое чувство было бы чем-то вроде "WTF!!!"

Посмотрите на это следующим образом:

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

  • Вы в основном заявляете, что вам слишком ленив, чтобы заботиться о освобождении памяти.

Ну, WTF снова. Лень - это не повод для чего-либо, а наименьшее из того, что играет с памятью, не освобождая ее.

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

Ответ 4

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

Ответ 5

Джоэл Коэхорн прав:

Это не должно вызывать никаких проблем.

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

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

Если вы хотите действительно простой способ освободить память, посмотрите концепцию "пулов" , которую использует Apache.

Ответ 6

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

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

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

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

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

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

Наконец: "Его вопрос о стиле... Небрежная работа имеет тенденцию к формированию привычки". - Шелк в Замке волшебства Дэвида Эддинга.

Ответ 7

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

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

Это потому, что вы не знаете, когда он должен быть выпущен? Оставьте память в объектах RAII, каждая из которых ссылается на что-то, и все они будут стекать друг с другом, когда освобождающийся объект освобождается - это особенно важно, если вы хотите запустить его как сервер в один прекрасный день, каждая итерация сервер эффективно запускает "главный" объект, который содержит все остальные, поэтому вы можете просто удалить его, и вся память исчезнет. Это также помогает предотвратить ретро-установку GC.

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

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

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

Ответ 8

Сравнение ссылок на интеллектуальные указатели, такие как shared_ptr в boost и TR1, также может помочь вам управлять своей памятью простым способом.

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

Ответ 9

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

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

Ответ 10

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

Если вы просто спешите или ленивы, и жизнь вашей программы мала по сравнению с тем, что она на самом деле выделяет (т.е. выделение 10 МБ в секунду не мало, если работает в течение 30 секунд).. тогда вы должны быть в порядке.

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

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

Ответ 11

Каково ваше отношение к этому?

Некоторые O/Ses могут не восстановить память, но я думаю, вы не собираетесь запускать эти O/Ses.

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

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

Ответ 13

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

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

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

Ответ 14

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

Ответ 15

Помимо того, что ОС (ядро и/или библиотека C/С++) может не освобождать память при завершении выполнения, ваше приложение должно всегда обеспечивать надлежащее освобождение выделенной памяти в качестве хорошей практики. Зачем? Предположим, вы решили продлить это приложение или повторно использовать код; вы быстро столкнетесь с проблемой, если код, который вы ранее писали, заведомо освобождает память после окончания работы. Это рецепт утечек памяти.

Ответ 16

В общем, я согласен, что это плохая практика.

Для программы с одним выстрелом это может быть хорошо, но это похоже на то, что вы не делаете то, что делаете.

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

Ответ 17

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

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

Если вы выделяете несколько огромных кусков памяти или много маленьких кусков.

Необходимо ли заблокировать память в физической памяти.

Вы абсолютно уверены, что необходимый код и память будут вписываться в 2 ГБ для системы Win32, включая отверстия в памяти и отступы.

Ответ 18

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

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

Ответ 19

При выходе из программы выделенная память automatically returned в систему. Таким образом, вы не можете освободить выделенную память.

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

Следовательно, всегда recommended to deallocate выделенная память.