.NET reference source доступно для просмотра всем, и вы можете посмотреть и узнать сами.
Если покопаться в GCHandle.Alloc
, вы увидите, что он вызывает нативный метод под названием InternalAlloc
:
[System.Security.SecurityCritical] // auto-generated
[MethodImplAttribute(MethodImplOptions.InternalCall)]
[ResourceExposure(ResourceScope.None)]
internal static extern IntPtr InternalAlloc(Object value, GCHandleType type);
свертывания в код CLR, вы видите внутренний вызов MarshalNative::InternalAlloc
, который заканчивается до вызова:
hnd = GetAppDomain()->CreateTypedHandle(objRef, type);
который в свою очередь вызывает ObjectHandle::CreateTypedHandle
->HandleTable::HndCreateHandle
->HandleTableCache->TableAllocSingleHandleFromCache
который выделяет ручку, если она не существует в кэше.
Как @Antosha исправил меня, место вызова не через ComDelegate
(что фактически мало что делает), но через MarshalNative
. Выделение происходит, а не на управляемой куче , но внешняя куча, зарезервированная средой выполнения для управления корнями ручек в объектах GC. Единственное выделение, которое делает, происходит в управляемой куче IntPtr
, которая удерживает указатель на адрес в таблице. Несмотря на это, вы все равно должны позвонить по телефону GCHandle.Free
, как только закончите.
Вероятно, вы пытаетесь рассказать вам, что мешает управляемому объекту собирать мусор. И да, это обычно будет GCHandle, необходимо сохранить, скажем, текстуру или живую сеть, которую вы передали OpenGL. Нехорошо, если они закрепляют ручки, они, вероятно, есть, но это всего лишь аспект любой используемой библиотеки обложек OpenGL. –
Профилировщик даже присваивает определенную сумму памяти каждому GCHandle, который я выделяю - 8 байтов. И управляемая куча, кажется, растет с 8 байтами с каждым GCHandle.Alloc. Похоже, что на самом деле он выделяет пространство на управляемой куче, хотя я понятия не имею, для чего? – kaalus
В CLR хранится отдельный стол дескриптора, где хранятся GCHandles. Конечно, 8 байт звучат правильно. Если это растет без ограничений, то вам, вероятно, не хватает требуемого вызова GCHandle.Free(), когда актив больше не нужен. –