views:

86

answers:

2

Can someone explain me why the below C# code doesn't crash? Why does Visual Studio actually allow to compile it? My understanding is that I am getting a fixed pointer, but it is fixed only within the 'fixed' statement. When the pointer is returned from the 'Foo' function, the array 'ar' may be collected. I then force GC to actually do this, but consecutive writing to the memory (which is now deallocated) doesn't cause any error.

class Program
{
    static unsafe byte* Foo()
    {
        byte[] ar = new byte[100];
        fixed (byte* ptr = ar)
        {
            return ptr;
        }
    }

    static unsafe void Main(string[] args)
    {
        byte* ptr = Foo();
        GC.Collect();
        for (int t = 0;;++t) ptr[t%100] = 0;
    }
}
+1  A: 

Just because the memory is freed doesn't mean that writing to it would cause an error of any kind. When the garbage collector reclaims memory, it just marks it as free in it's internal memory map -- it doesn't give it back to the OS right away, so it's still valid memory for your process to use.

Of course, using a pointer outside of the fixed block for it is a very bad idea -- don't do it.

Jonathan
But do you know why it didn't cause a compile-time error? If it is an obvious error, then I think compiler should produce an error message.
Michal Czardybon
See where it says "unsafe"? That's you telling the compiler "I know what I am doing and I am taking responsibility for the type safety of this dangerous code". The compiler does not warn because it believes you when you said that you knew what you were doing.
Eric Lippert
+1  A: 

Eric is right, but the answer you probably want to hear is that "sometimes it's useful to retain the address outside of the fixed statement".

Maybe the memory from that pointer is already fixed by another fixed statement somewhere else, and it makes sense to return it? The compiler is not trying to second guess you and give noisy warnings.

That said, I'd hope that CodeAnalysis or other advanced tools would step in here where the compiler is letting you cut off your own foot.