Search code examples
c#garbage-collectionunsafe

Nested 'fixed' statement


According to the C# reference for fixed statement:

The fixed statement prevents the garbage collector from relocating a movable variable. ... After the code in the statement is executed, any pinned variables are unpinned and subject to garbage collection. Therefore, do not point to those variables outside the fixed statement.

What I haven't found on this page: What will it be if we have nested the fixed statement for the same variable?

var data = new byte[100];
unsafe
{
    fixed(byte* pData = data)
    {
        //pData points to the "pinned" variable
        fixed(byte* pData2 = data)
        {
            //pData points to the "pinned" variable
            //pData2 points to the "pinned" variable
        }
        //Does pData still point to the "pinned" variable?
    }
}

The code above is thought of course only for illustration. The practical use could be recursive functions.


Solution

  • This works just the way you'd expect it to work, necessarily so. The fixed property is associated with the pointer variable, not the object that it pins. So inside the inner scope block there are two variables that pin the array. Next one up there is one variable that pins it. It is still pinned.

    When you recurse, and the array is declared outside of the method, then there will be a lot more variables that pin it.

    The decent mental image is to work from the assumption that fixed initializes a GCHandle for the object. You can create as many GCHandles for an object as you dare, the GC does not mind. That doesn't actually happen at runtime, fixed is much more efficient than a GCHandle. It is an attribute of the variable, shown as [pinned] in a disassembler like ildasm.exe. The GC discovers the attribute when it walks the stack, looking for object references.