2015-11-03 5 views
5

У меня есть класс C#, имеющий статический объект ImageList. Этот список изображений будет совместно использоваться различными заголовками ListView (через SendMessage ... HDM_SETIMAGELIST) в нескольких формах в моем приложении.Связаны ли статические члены класса?

Хотя я понимаю, что статические объекты не могут быть использованы для сбора мусора, мне не ясно, если они также не имеют права на перемещение (уплотнение) сборщиком мусора. Нужно ли мне также связывать этот объект, поскольку он используется совместно с неуправляемым кодом, скажем, с помощью GCHandle.Alloc?

Окружающая среда - VS 2008, Compact Framework 3.5.

+0

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

ответ

0

Должен ли я также связывать этот объект, поскольку он используется совместно с неуправляемым кодом , скажем, с использованием GCHandle.Alloc?

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

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

EDIT

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

0

Да. Вам нужно привязать объект.

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

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

Кроме того, каждый статический член является unqiue для AppDomain (а ​​не процесса). Один и тот же статический член может существовать в разных местах памяти в одном и том же процессе, и это может быть сбор мусора, когда AppDomain выгружается. Это довольно краткий случай, который я допущу, но нет никакого реального преимущества не закреплять объекты, даже если это можно было бы сделать без фиксации.

+0

Объект MyListList предоставляет свойство Handle, которое я передаю неуправляемому коду, а не значение, возвращаемое AddrOpPinnedObject(). Должен ли я привязывать только свойство Handle (которое представляет собой структуру IntPtr) или весь объект ImageList? – dablumen

+0

Вы должны привязать объект для доступа к объекту с помощью метода 'AddrOpPinedObject()'. Тем не менее, это приведет к необработанному указателю на управляемый объект, если он не является массивом, который является ** blittable **. Я думаю, на самом деле вы получаете исключение, если вы делаете это с не-blittable типами, как и должно быть. Передача Handle напрямую связана с передачей 'gc_root', которая является только оболочкой вокруг' GCHandle', и она будет действовать соответствующим образом и связывать объект по мере необходимости для доступа из неуправляемого кода. –

2

Сам экземпляр не является статичным. Ссылка есть. Если вы упустили ссылку, экземпляр получит право на GC. Внутри все статические экземпляры являются ссылками через закрепленный дескриптор в массив статики. То есть экземпляр неявно закрепляется средой выполнения.

Если вы посмотрите на GCroot экземпляра объявлен как статический член, вы увидите что-то вроде этого:

HandleTable: 
    008113ec (pinned handle) 
    -> 032434c8 System.Object[] 
    -> 022427b0 System.Collections.Generic.List`1[[System.String, mscorlib]] 

Если обнулить статическую ссылку соответствующая запись в массиве возлагали обнуляется, как Что ж.

Теперь это, очевидно, детали реализации, поэтому они могут потенциально измениться.

+0

это интересно. Есть ли у вас некоторые возможности по внедрению? (статьи, блоги ..) Потому что, похоже, нет большой информации о предмете, о котором вы говорите. – Tigran

+0

Это детали реализации, я полагаю, но вы можете копаться вокруг этого с помощью WinDbg/SOS и видеть, что статические файлы обрабатываются следующим образом. –

+0

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