Free mag vol1 | Page 496

CHAPTER 11  ADVANCED C# LANGUAGE FEATURES unsafe static void UnsafeStackAlloc() { char* p = stackalloc char[256]; for (int k = 0; k < 256; k++) p[k] = (char)k; } Pinning a Type via the fixed Keyword As you saw in the previous example, allocating a chunk of memory within an unsafe context may be facilitated via the stackalloc keyword. By the very nature of this operation, the allocated memory is cleaned up as soon as the allocating method has returned (as the memory is acquired from the stack). However, assume a more complex example. During our examination of the -> operator, you created a value type named Point. Like all value types, the allocated memory is popped off the stack once the executing scope has terminated. For the sake of argument, assume Point was instead defined as a reference type, like so: class PointRef // <= Renamed and retyped. { public int x; public int y; public override string ToString() { return string.Format("({0}, {1})", x, y); } } As you are aware, if the caller declares a variable of type Point, the memory is allocated on the garbage-collected heap. The burning question then becomes, “What if an unsafe context wants to interact with this object (or any object on the heap)?” Given that garbage collection can occur at any moment, imagine the problems encountered when accessing the members of Point at the very point in time such a sweep of the heap is under way. Theoretically, it is possible that the unsafe context is attempting to interact with a member that is no longer accessible or has been repositioned on the heap after surviving a generational sweep (which is an obvious problem). To lock a reference type variable in memory from an unsafe context, C# provides the fixed keyword. The fixed statement sets a pointer to a managed type and “pins” that variable during the execution of the code. Without fixed, pointers to managed variables would be of little use, since garbage collection could relocate the variables unpredictably. (In fact, the C# compiler will not allow you to set a pointer to a managed variable except in a fixed statement.) Thus, if you create a PointRef type and want to interact with its members, you must write the following code (or receive a compiler error): unsafe public static void UseAndPinPoint() { PointRef pt = new PointRef (); pt.x = 5; pt.y = 6; // Pin pt in place so it will not // be moved or GC-ed. fixed (int* p = &pt.x) { 436