Re: Garbage collectable pinned arrays!
- From: "Willy Denoyette [MVP]" <willy.denoyette@xxxxxxxxxx>
- Date: Tue, 12 Feb 2008 20:08:08 +0100
"Ben Voigt [C++ MVP]" <rbv@xxxxxxxxxxxxx> wrote in message news:ummJ1AZbIHA.5164@xxxxxxxxxxxxxxxxxxxxxxx
The array is automatically allocated on the heap once it exceeds
a certain size and thu's becomes "pinned", because the heap is
never compacted and all addresses are absolute.
Arrays that exceed a certain size (85Kb currently), are moved to the
Large Object Heap, but they aren't pinned by this. The LOH is not
compacted, but that doesn't mean that the objects cannot get
collected.
All objects on the LOH are pinned at all times, by the nature of the heap (non-compacting).
This is not what pinned means in this context. The objects on the LOH (all version of the CLR) are at a fixed address for their life time, but that doesn't mean they are pinned. Pinning is an explicit action that allocated an Object Handle and stores it in the GCHandles table and set's the "pinned" bit (don't know exactly where this bit is set as this changes from one release to another).
If you want to see pinning in action you'll have to run your code in a native debugger and load sos.
For instance consider following snip:
...
double[] a2 = new double[20000];
a2[a2.Length-1]= 0.7889;
// Break here and watch the Handles table, using !sos.gchandles
GCHandle h = GCHandle.Alloc(soa, GCHandleType.Pinned);
// break again and watch the handles table again, you will see
// 1) the: Pinned Handles: value that was incremented
// 2) and object reference is added to the table, object reference which is pointing to the actual array object.
...
The same thing happens when "PInvoking", but now the pinning is only done when the GC kicks in. Note that you need to explicitly pin when passing a buffer (or callback) to unmanaged when there is a chance that your buffer gets accessed after the call returned. Do you know exactly what gets done in the unmanaged function? You better do!, the function can kick off another thread pass the address of the buffer and return. The object passed-in is no longer protected when the GC comes along, the thread that accesses the object is subject to AV exceptions!
It would be useful to request that a particular buffer not be subject to relocation by the GC. Probably the easiest way to do this would be to place it in the LOH. The OLE task allocator or HGlobal allocator, both of which are already exposed by the Marshal class in a typeless way, would be other options. It could be as simple as adding a T[] Marshal.AllocCoTaskMem<T>(int elementCount) override.
But now you are allocating from the unmanaged heap (COM heap or CRT heap or whatever). So now you will incur the costs of copying back and forth, again this depends on the semantics, but might be a solution when you need to pass large data chunks to unmanaged land.
Willy.
.
- Follow-Ups:
- Re: Garbage collectable pinned arrays!
- From: Ben Voigt [C++ MVP]
- Re: Garbage collectable pinned arrays!
- References:
- Re: Garbage collectable pinned arrays!
- From: Jesse McGrew
- Re: Garbage collectable pinned arrays!
- From: Atmapuri
- Re: Garbage collectable pinned arrays!
- From: Willy Denoyette [MVP]
- Re: Garbage collectable pinned arrays!
- From: Ben Voigt [C++ MVP]
- Re: Garbage collectable pinned arrays!
- Prev by Date: Re: Get Current Time in Different Timezone
- Next by Date: Re: Multithreaded GC!
- Previous by thread: Re: Garbage collectable pinned arrays!
- Next by thread: Re: Garbage collectable pinned arrays!
- Index(es):
Relevant Pages
|
Loading