Может ли сборка мусора сосуществовать с явным управлением памятью? - PullRequest
8 голосов
/ 25 октября 2008

Например, скажем, один должен был включить ключевое слово delete в C # 4. Можно ли было бы гарантировать, что у вас никогда не будет диких указателей, но вы все равно сможете полагаться на сборщик мусора, благодаря ссылке система?

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

РЕДАКТИРОВАТЬ: Я не говорю только о .net. Я просто использовал C # в качестве примера.

Ответы [ 9 ]

3 голосов
/ 25 октября 2008

Вы можете - своего рода: сделать свой предмет одноразовым, а затем утилизировать его самостоятельно.

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

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


Идея для реализации удаления: удалить теги объект для ручного удаления. На следующем цикле сборки мусора объект удаляется, и для всех ссылок на него устанавливается значение null.

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

2 голосов
/ 25 октября 2008

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

Пример (псевдокод):

obj1 = new instance;
obj2 = obj1;

// 

delete obj2;
// obj1 now references the twilightzone.

Проще говоря, сочетание ручного управления памятью и сбора мусора наносит ущерб цели GC. Кроме того, зачем? И если вы действительно хотите иметь контроль, используйте C ++, а не C #. ; -.)

1 голос
/ 25 октября 2008

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

0 голосов
/ 19 декабря 2011

Да ... но с некоторым оскорблением.

C # можно немного злоупотребить, чтобы это произошло. Если вы хотите поиграть с классом Marshal, атрибутом StructLayout и unsafe code, вы можете написать свой собственный ручной менеджер памяти.

Демонстрацию этой концепции можно найти здесь: Написание ручного диспетчера памяти на C # .

0 голосов
/ 16 августа 2010

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

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

0 голосов
/ 30 января 2010

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

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

Задачей GC будет очистить эти скрытые ссылки.

0 голосов
/ 15 августа 2009

Это возможно и уже реализовано на неуправляемых языках, таких как C ++. По сути, вы реализуете или используете существующий сборщик мусора: когда вы хотите ручное управление памятью, вы вызываете new и delete как обычно, а когда вы хотите сборку мусора, вы вызываете GC_MALLOC или любую другую функцию или макрос для сборщика мусора. *

См. http://www.hpl.hp.com/personal/Hans_Boehm/gc/ для примера.

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

0 голосов
/ 26 октября 2008

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

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

Однако проблема заключается здесь:

String s = "Here is a string."; 
String t = s;
String u = s;
junk( s );

На что указывают t и u? В строгой системе отсчета t и u должны быть null. Таким образом, это означает, что вам нужно не только сделать ссылку , считающую , но, возможно, отслеживающую .

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

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

0 голосов
/ 25 октября 2008

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

http://www.dotnetrocks.com/default.aspx?showNum=10

...