简体   繁体   中英

Are static class members pinned?

I have a C# class, having a static ImageList object. This image list will be shared with various ListView headers (via SendMessage... HDM_SETIMAGELIST) on several forms in my application.

Though I understand that static objects are not eligible for garbage collection, it is not clear to me if they are also ineligible for relocation (compaction) by the garbage collector. Do I also need to pin this object since it is shared with unmanaged code, say, using GCHandle.Alloc?

Environment is VS 2008, Compact Framework 3.5.

The instance itself is not static. The reference is. If you null the reference the instance becomes eligible for GC. Internally, all static instances are references through a pinned handle to an array of statics. Ie the instance is implicitly pinned by the runtime.

If you look at the GCroot of an instance declared as a static member, you'll see something like this:

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

If you null the static reference the corresponding entry in the pinned array is nulled as well.

Now, these are obviously implementation details so they could potentially change.

Do I also need to pin this object since it is shared with unmanaged code, say, using GCHandle.Alloc?

Yes. If the pointer is not pinned, GC is free to move that memory, so you may have dangling C++ pointers, pointing to some non valid, or worse, non their memory at all.

Also, "shared" word should be clarified. If you allocate and pass to unmanaged memory, which copies it somewhere, you may avoid to pin them constantly. Depends on what happens once you pass control to unmanaged environment.

EDIT

Even considering interesting answer from @Brian, I would still opt for pinning the pointer. To make explicit in the code the notion of the fixed pointer, avoid any possible misguide in future code maintenance and keep clarity.

Yes. You need to pin the object.

While it's true that the reference is static, that is, you may access this location anywhere from your member it's reference is still a GC handle. That is, it's eligible for garbage collection (and/or compaction) but it will of course never happen.

I don't think it's necessarily wrong to think that the static modifier implies that it will eventually have a static location in memory but there bigger issue is that there's no API that allows you to get at the memory address without pinning the object. Whether it's being moved by the GC or not.

Moreover, each static member is unqiue per AppDomain (not process). The same static member could exist in different memory locations in the same process and it can be garbage collected when the AppDomain unloads. This is quite the edge case I'll admit but there's no real advantage of not pinning objects even if it could be done without pinning.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM