0

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

4

2 回答 2

2

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

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

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

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

于 2014-04-09T12:10:57.100 回答
1

NullReferenceException您取消引用一个对象引用时会发生null. null是 CLR 上的一个特殊值,表示“无对象”。这并不意味着空指针。实际上,它是一个空指针,但这是一个实现细节。

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

于 2014-04-09T11:51:24.943 回答