有人可以解释一下为什么下面的C#代码不会崩溃吗?为什么Visual Studio实际上允许编译它?我的理解是我得到一个固定的指针,但它只在'fixed'语句中修复。当指针从'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;
}
}
答案 0 :(得分:1)
仅仅因为释放内存并不意味着写入它会导致任何类型的错误。当垃圾收集器回收内存时,它只是在它的内部内存映射中将其标记为空闲 - 它不会立即将其返回给操作系统,因此它仍然是有效的内存供您的进程使用。
当然,在固定块之外使用指针是一个非常坏主意 - 不要这样做。
答案 1 :(得分:1)
Eric是对的,但您可能希望听到的答案是“有时保留固定语句之外的地址很有用”。
也许该指针的内存已经被其他地方的另一个固定语句修复了,返回它是否有意义?编译器不会试图猜测你并发出嘈杂的警告。
那就是说,我希望CodeAnalysis或其他高级工具能够在这里让编译器让你自己切断。