Допустимо ли не освобождать память - PullRequest
14 голосов
/ 30 января 2009

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

program-name input-file

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

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

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

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

Ответы [ 19 ]

22 голосов
/ 30 января 2009

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

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

15 голосов
/ 02 февраля 2009

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

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

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

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

13 голосов
/ 30 января 2009

Мне кажется, что-то вроде "WTF !!!"

Посмотрите на это так:

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

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

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

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

8 голосов
/ 30 января 2009

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

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

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

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

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

8 голосов
/ 30 января 2009

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

5 голосов
/ 30 января 2009

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

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

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

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

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

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

Наконец: «Это вопрос стиля ... Небрежная работа, как правило, вызывает привыкание». - Шелк в Замок Волшебства Дэвид Эддингс.

3 голосов
/ 30 января 2009

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

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

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

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

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

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

3 голосов
/ 30 января 2009

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

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

3 голосов
/ 02 февраля 2009

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

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

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

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

3 голосов
/ 30 января 2009

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

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

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