Memory & GC
using System.Runtime.InteropServices;
var buffer = new byte[] { 4, 8, 15, 16 };
var handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
try
{
Console.WriteLine($"handle:{handle.IsAllocated}");
buffer[0] = 42;
Console.WriteLine($"first:{buffer[0]}");
}
finally { handle.Free(); }
Console.WriteLine($"released:{!handle.IsAllocated}");
GC.KeepAlive(buffer);
Reveal answer and reasoning
The portable program allocates four bytes and creates one pinned GCHandle. Inside try, IsAllocated is true and writing the first element changes it to 42. The finally block frees the owned handle. The following check reports released:True. The ordinary buffer is explicitly kept alive afterward so the code distinguishes ending the pin from ending managed ownership.
The example never obtains a raw pointer and never calls native code. It therefore demonstrates a bounded handle lifetime without pretending to validate a native protocol. Its output does not identify a physical heap address or prove POH placement. Pinning the existing byte array is precisely the operation that must not be described as migration to POH. If you add a pointer experiment, keep it in a suitable desktop environment and preserve the lease.
The pinning lab uses conceptual slots. A dead temporary creates a hole before a pinned buffer, and a live movable buffer starts farther away. Step through collection with the pin active, then reset and remove the pin. The toy compactor packs only within pin-separated regions. That rule is deliberately visible and is not a claim that CoreCLR uses the exact same placement strategy or slot sizes.
The SDK experiment compares an existing pinned array with an allocate-pinned array and prints actual generation and pinned-count observations. Generation 2 alone is not proof that an object is in POH because ordinary Gen 2 and LOH objects can also report that generation. PinnedObjectsCount is a collection observation, not an exact inventory of every address lease at the instant of printing.
Use a matching-runtime diagnostic tool for region attribution.
What a strong answer covers
- Pinning an existing object does not migrate it to POH.
- A pointer lease must end after native consumption, not merely after submission.
- POH objects remain collectible when no strong owner remains.
Common pitfall
Claiming that pinning an existing array moves it to POH, or freeing a pin before asynchronous native consumption ends.
Follow-up questions
- What acknowledgement permits releasing a pin after cancellation?
- Can generation2 alone distinguish POH from other storage?
Self-review
Choose what to revisit. These marks are your own assessment and are separate from lesson completion.