空引用异常与零指针访问冲突

本文关键字:指针 访问冲突 引用 异常 | 更新日期: 2023-09-27 17:57:30

最近我读了一本关于c#的书,对null引用异常与指针被取消引用时本机代码中的访问冲突不同的说法感到非常困惑。我不清楚这是什么意思,你能解释一下吗?

空引用异常与零指针访问冲突

在本机代码中,您可以使用指针直接访问内存位置。如果指针是32位,您可以访问大约40亿个虚拟内存位置(2^32)。然而,并非所有虚拟内存位置都映射到物理内存,并且其中一些位置仅映射为只读(例如代码)。如果本机代码试图访问不可访问的虚拟内存位置,则会在CPU上发生访问冲突。

因此,当您使用无效指针(读取或写入指针指向的位置)时,就会发生访问冲突。硬件内存管理器的保护通过捕获CPU上的无效访问并引发某种形式的错误条件或异常来帮助您发现这些错误。但是,您也可能具有无效指针,从而导致访问可访问的内存位置。即使访问无效,CPU也不会发现它,这可能会导致内存损坏和其他难以修复的错误。

本机代码中的一个常见错误是在使用指针之前忘记初始化指针。通常指针会指向地址0(也称为空指针)。捕获此类错误的策略是使虚拟地址空间中的第一页(从地址0开始)不可访问。当无效指针被取消引用时,就会出现访问冲突。因此,在本机代码中,由于地址0不可访问,空指针错误被报告为访问冲突。

.NET在虚拟机上执行,并且不提供指针(除非您编写不安全的代码)。访问冲突的概念不适用于.NET代码。但是,可以取消初始化.NET引用(例如null)。当空引用被取消引用时,虚拟机将抛出一个NullReferenceException。从概念上讲,这与如上所述将本机代码空指针错误报告为访问违规的方式有些相似,但概念和机制不同。

当取消引用null的对象引用时,会发生NullReferenceExceptionnull是CLR上的一个特殊值,表示"无对象"。它不是指空指针。在实践中,它是一个空指针,但这是一个实现细节。

对于托管代码,AccessViolationException没有意义,因为在托管代码中没有指针。不要将概念级别与当前实现混淆。