Что такое закрепленные объекты? - PullRequest
42 голосов
/ 22 марта 2010

Я пытаюсь найти утечку памяти с помощью профилировщика памяти муравьев, и я столкнулся с новым термином:

Закрепленные объекты.

Может ли кто-нибудь дать мне хорошее и простое объяснение того, что это за объекты, как я могу закрепить / открепить объекты и определить, кто закрепил объекты?

Спасибо

Ответы [ 7 ]

51 голосов
/ 22 марта 2010

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

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

Закрепление объекта говорит GC НЕ ДВИГАТЬСЯ. Обычно это бесполезно и ТОЛЬКО имеет смысл при работе с указателями - как при использовании PInvoke. Иногда вам нужно включить адрес в структуру (в терминах разметки памяти), и если это реализовано в классе, вы должны закрепить это.

На конкретный ответ:

  • Вы не можете узнать, кто прикрепил объект.
  • Закрепление выполняется с помощью оператора FIXED. Это допускается только в небезопасном коде.

Проверка:

http://msdn.microsoft.com/en-us/library/f58wzh21%28VS.80%29.aspx

19 голосов
/ 22 марта 2010

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

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

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

6 голосов
/ 22 марта 2010

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

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

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

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

6 голосов
/ 22 марта 2010

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

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

5 голосов
/ 22 марта 2010

Для закрепления объектов вы можете использовать ключевое слово fixed :

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

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

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

4 голосов
/ 22 марта 2010

Закрепленный объект - это объект, который имеет заданное местоположение в памяти.

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

Вы можете создать их, используя оператор fixed: http://msdn.microsoft.com/en-us/library/f58wzh21%28VS.80%29.aspx

2 голосов
/ 22 марта 2010

получил от MSDN «Закрепленный объект - это объект, который сборщик мусора не может перемещать в памяти»

http://msdn.microsoft.com/en-us/library/x2tyfybc(VS.71).aspx

...