[Previous] [Contents] [Next]

The fixed Statement

The fixed statement has the following syntax: -

fixed (type * ptr = expression) statement -

As I mentioned, the statement tells the GC not to bother with the specified variable. Note that type is an unmanaged type or void, expression is any expression that results in a type pointer, and statement refers to the block of code for which the pinning of the variable is applicable. A simple example follows.

using System;

class Foo
{
    public int x;
}

class Fixed1App
{
    unsafe static void SetFooValue(int* x)
    {
        Console.WriteLine("Dereferenced pointer to modify foo.x");
        *x = 42;
    }

    unsafe static void Main()
    {
        // Create an instance of the structure.
        Console.WriteLine("Creating the Foo class");
        Foo foo = new Foo();

        Console.WriteLine("foo.x intialized to {0}", foo.x);

        // The fixed statement pins the foo object until
        // the enclosing compound statement ends.
        Console.WriteLine("Setting pointer to foo.x");
        // Assign the address of the foo object to a Foo*.
        fixed(int* f = &foo.x)
        {
            Console.WriteLine("Calling SetFooValue passing " +
                              "pointer to foo.x");
            SetFooValue(f);
        }

        // Show that we did alter the member via its pointer.
        Console.WriteLine("After return from " +
                          "SetFooValue, foo.x = {0}", foo.x);
    }
}

This code instantiates a class called Foo and, within a fixed statement, pins that object while assigning the address of its first member to a variable of type int* (the type required by the method SetFooValue). Note that the fixed statement is used only to enclose the code that will be affected if the GC were to move the Foo object. This is a subtle, yet important, issue for larger and longer running code blocks where you want to minimize the amount of time you have an object pinned. Compiling and executing the code above results in the following output: -

Creating the Foo class
foo.x intialized to 0
Setting pointer to foo.x
Calling SetFooValue passing pointer to foo.x
Dereferenced pointer to modify foo.x
After return from SetFooValue, foo.x = 42
NOTE
One important point about pinned variables is the fact that the C# compiler does not restrict access to a pinned variable to the unsafe scope. For example, you can use a pinned variable as an r-value to an l-value that is defined in a broader scope than the unsafe block. Obviously, this can result in an unsafe value being used outside of the unsafe block. In lieu of the compiler emitting a warning or error in this case, it is the developer's responsibility to take care when using pinned variables as r-values.

[Previous] [Contents] [Next]