我在为Code Golf上的一个问题尝试使用不安全代码,但我发现了一个无法解释的问题。以下是我的代码:
unsafe
{
int i = *(int*)0;
}
出现访问冲突(段错误)导致崩溃,但是这段代码:
unsafe
{
*(int*)0=0;
}
抛出一个NullReferenceException异常。在我看来,第一个是进行读取操作,第二个是进行写入操作。异常告诉我,在CLR中的某处拦截了写入操作,并在操作系统杀死该进程之前停止了它。为什么对写入操作会发生这种情况,而对读取操作则没有?如果我将指针值设置得足够大,则会在写入时发生段错误。这是否意味着CLR知道有一块内存是保留的,并且甚至不会尝试写入它?那么,为什么它允许我尝试从该块中读取数据?我完全误解了什么吗?
编辑:
有趣的是:System.Runtime.InteropServices.Marshal.WriteInt32(IntPtr.Zero, 0);
导致访问冲突,而不是NullReference。
*(int*)-1
会得到AVE。更多信息请参考这里:https://dev59.com/dWsz5IYBdhLWcg3wYGoz#7940659。 - Hans Passant