Почему использовать сборщик "мусора"? [дубликат]

18
задан Community 23 May 2017 в 12:13
поделиться

22 ответа

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

19
ответ дан 30 November 2019 в 05:40
поделиться

Сборка мусора может быть более эффективной.

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

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

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

1
ответ дан 30 November 2019 в 05:40
поделиться

Как вы упомянули, вы можете сделать свою собственную сборку мусора. Добавление сборщика мусора просто избавляет вас от необходимости беспокоиться об этом и от необходимости тратить время на написание и тестирование кода сборки мусора. Если вы работаете с существующей базой кода, содержащей утечки памяти, может быть проще (и эффективнее) использовать автоматический сборщик мусора, чем пытаться изучить весь существующий код достаточно подробно, чтобы найти и исправить проблемы.

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

0
ответ дан 30 November 2019 в 05:40
поделиться

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

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

4
ответ дан 30 November 2019 в 05:40
поделиться

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

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

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

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

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

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

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

8
ответ дан 30 November 2019 в 05:40
поделиться

Вам может потребоваться как можно скорее освободить ресурсы Interop (заблокированный файл). Gc.Collect может гарантировать освобождение COM-объектов (если на них нет ссылок).

Если вы выполняете PrintPreview, это требует 2 дескриптора Gdi для каждой страницы (изображение + метафайл). Эти ресурсы не освобождаются PrintDocument или PrintControler, они ждут GC.

Я тестировал интерактивную программу на использование Gc.Collect, когда пользователь возвращается в главное меню. При этой операции заявленный объем памяти для диспетчера задач составляет около 50%.

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

0
ответ дан 30 November 2019 в 05:40
поделиться

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

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

.
0
ответ дан 30 November 2019 в 05:40
поделиться

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

1
ответ дан 30 November 2019 в 05:40
поделиться

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

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

Причина проста. Я работаю с программистами, которые являются одними из лучших в своей области. Не опасаясь преувеличения, могу сказать, что некоторые из них написали книгу в своей области.И все же эти люди программируют на C ++ и допускают ошибки с управлением памятью. Когда они совершают эти ошибки, их особенно трудно найти и исправить. Почему удивительные люди, чьи таланты можно было бы направить в другое место, тратят свое время на то, что машина могла бы сделать лучше?

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

1
ответ дан 30 November 2019 в 05:40
поделиться

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

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

  1. проблема проста (например, недолговечное приложение командной строки) и программист достаточно дисциплинирован;
  2. программист - Дональд Кнут .

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

2
ответ дан 30 November 2019 в 05:40
поделиться

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

Такова, по крайней мере, теория. Проблема в том, что это может сильно усложнить код. Например, this:

for (x in ComputeBigList()) ...

превращается в this

var xs = ComputeBigList();

try {
   for(x in xs) ...
} finally {
   FreeMemory(xs);
}

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

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

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

.
2
ответ дан 30 November 2019 в 05:40
поделиться

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

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

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

2
ответ дан 30 November 2019 в 05:40
поделиться

В наши дни большинство людей, использующих сборщик мусора, делают это внутри управляемой среды (например, виртуальной машины Java или среды CLR .NET). Эти управляемые среды добавляют дополнительную сложность: они ограничивают возможность принимать указатели на вещи . В CLR, например, есть понятие указателя (который можно использовать через управляемый IntPtr или неуправляемый небезопасный блок кода), но есть ограниченные условия, когда вы ' им разрешено использовать их. В большинстве случаев вам нужно «закрепить» соответствующие объекты в памяти, чтобы GC не перемещал их, пока вы работаете с их указателями.

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

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

Наконец, сборка мусора становится действительно необходимой при работе с языками функционального программирования (или программированием в функциональных стилях). Фактически, самый первый сборщик мусора был изобретен Маккарти в 1959 году как часть разработки языка Lisp. Причина двоякая: во-первых, функциональное программирование поощряет неизменяемые структуры данных, которые легче собирать, и, во-вторых, в чистом функциональном программировании нет функции распределения; память всегда выделяется как «стек» (локальные функции), а затем перемещается в «кучу», если она захвачена закрытием . (Это грубое упрощение, но служит для иллюстрации сути.)

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

3
ответ дан 30 November 2019 в 05:40
поделиться

Потому что мы недостаточно мудры.

8
ответ дан 30 November 2019 в 05:40
поделиться

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

За свой короткий опыт работы программистом я потратил (накопил) дни, пытаясь выяснить, почему valgrind (или другие подобные инструменты) сообщает об утечках памяти, когда все было так «грамотно закодировано».

4
ответ дан 30 November 2019 в 05:40
поделиться

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

10
ответ дан 30 November 2019 в 05:40
поделиться

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

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

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

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

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

13
ответ дан 30 November 2019 в 05:40
поделиться

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

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

Другой способ избежать сборки мусора - использовать язык, который не отделяет ссылку от содержимого . В этом случае настоящая утечка памяти невозможна. (Но, конечно, все еще можно использовать слишком много памяти.) ИМХО, языки высокого уровня вообще не должны связываться с «указателями» (адресными переменными).

2
ответ дан 30 November 2019 в 05:40
поделиться

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

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

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

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

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

0
ответ дан 30 November 2019 в 05:40
поделиться

Рассмотрим случай, когда конкретный указатель используется двумя отдельными подсистемами. Одна подсистема может быть создана с помощью переменной, и программист может подумать: «Я закончил с этим, я просто пойду дальше и освободю ее», совершенно не подозревая, что другой подсистеме все еще нужен доступ к ней. Или еще одна ловушка, думает разработчик: «Я не уверен, есть ли другая подсистема, которая может нуждаться в этом» (даже если ее нет), что приводит к утечке памяти. Подобные ситуации часто возникают в сложных системах.

5
ответ дан 30 November 2019 в 05:40
поделиться

управление памятью - это вопрос реализации, который не связан с целью программы.

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

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

0
ответ дан 30 November 2019 в 05:40
поделиться

Итак, зачем использовать сборщик мусора, если все, что вам нужно сделать, это просто разумно выделить / освободить память?

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

Если у вас есть простая программа (нулевой уровень сложности), вы можете просто использовать выделение на основе стека для обработки всего. Таким образом очень легко получить правильное распределение памяти, но это также очень ограниченная модель вычислений (и вы также сталкиваетесь с проблемами с пространством стека). Итак, вы начинаете использовать кучу; вот где начинается «веселье».

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

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

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

1
ответ дан 30 November 2019 в 05:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: