0

有人可以解释一下为什么下面的 C# 代码不会崩溃吗?为什么 Visual Studio 实际上允许编译它?我的理解是我得到了一个固定的指针,但它仅在“固定”语句中是固定的。当指针从'Foo'函数返回时,可以收集数组'ar'。然后我强制 GC 实际执行此操作,但连续写入内存(现在已解除分配)不会导致任何错误。

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;
    }
}
4

2 回答 2

1

仅仅因为内存被释放并不意味着写入它会导致任何类型的错误。当垃圾收集器回收内存时,它只是在其内部内存映射中将其标记为空闲——它不会立即将其返回给操作系统,因此它仍然是供您的进程使用的有效内存。

当然,在固定块之外使用指针是一个非常糟糕的主意——不要这样做。

于 2009-05-14T12:12:14.863 回答
1

Eric 是对的,但您可能想听到的答案是“有时将地址保留在固定语句之外很有用”。

也许该指针的内存已经被其他地方的另一个固定语句修复了,返回它是否有意义?编译器不会试图猜测你并给出嘈杂的警告。

就是说,我希望 CodeAnalysis 或其他高级工具能介入编译器让你断掉自己的脚的地方。

于 2009-05-14T18:53:23.107 回答