回答

0

Memory Management Unit在取消引用NULL指针或访问无效地址时在异常触发中起着关键作用。

MMU对每个RAM访问进行的正常虚拟到物理内存映射过程中,在MMU descriptors中定义的虚拟地址范围内找不到未定义的地址。如果发生在操作系统内核空间中,或者只是在用户空间域中进行杀死和清理,这可能会造成灾难性后果。

0

...怎么回事操作系统(Linux的说)可以确定当有空地址的访问,在代码中的某处,,而无需在代码中访问每一个指针地址

那么,操作系统无法在不访问指针的情况下确定NULL解引用。从wiki为分段错误:

在计算中,段故障(常缩写为段错误)或访问冲突是通过硬件具有存储器保护提出了一个故障,关于存储器通知操作系统(OS)访问违规;在x86计算机上,这是一种常规保护错误。操作系统内核将作出响应通常会执行一些纠正措施,通常通过向进程发送一个信号来将错误传递到违规进程。...

内存访问冲突是一个运行时事件,除非有一个无效的访问,没有办法操作系统会提高信号的过程。

FWIW,允许进程访问为其分配的内存(在虚拟地址空间中)。在分配的虚拟地址空间之外的任何地址(如果被访问)将产生故障(通过MMU),这反过来产生分段故障。

TL; DR - 在遇到NULL指针解引用时生成SIGSEV,而不是在此之前。此外,操作系统不会检测到本身的错误访问,而是通过raising a fault通知Memory Management Unit

+0

但是有没有其他方法(除了sigsegv)找出一个null derefrence? –

+0

@wannabeprogrammer可能在取消引用之前进行NULL检查? –

1

指针指的是虚拟地址空间。在虚拟地址空间中,内存的每个内存都可以映射到真实的物理内存。操作系统分别为每个进程处理此映射。

当您通过指针访问内存时,CPU会查看指针指定的虚拟地址的映射,并检查是否存在真实的物理内存。进行额外的检查来验证您是否具有对该内存的读取或写入权限,具体取决于您尝试的操作。

如果没有为该地址映射的内存,CPU会生成一个硬件中断。操作系统捕获该中断,并且 - 通常 - 为调用进程发出sigsegv信号。

包含NULL地址的零页通常会故意保留未映射的位置,以便通常由编程错误导致的NULL指针访问很容易被捕获。

0

Linux从硬件获得此支持。处理器会被告知个别内存区域的用途及其可用性。如果访问“不可用”的内存区域,处理器会通知操作系统有关问题,操作系统会通知应用程序。

这意味着两件事情:

  • 存在与检查对NULL值的所有指针没有软件开销。
  • 没有精确检查允许的指针值。

换句话说,如果指针指向“可用”内存的任何位置,则硬件单元无法识别问题。

1

首先空指针访问不一定是无效的。通常,操作系统的程序加载器或链接器(取决于系统)设置进程,以便虚拟地址空间中的最低页面未映射。

许多这样做的系统也允许应用程序映射第一页,使空引用有效。

NULL指针的检查方式与检查所有其他内存地址的方式相同:通过CPU的逻辑地址转换。

处理器每次访问内存(忽略缓存)时,都会查找进程页表中的地址。如果没有相应的条目,处理器会触发访问错误(在Unix中,变量会被转换为信号)。

如果地址在页表中有条目,处理器会检查页面允许的访问。如果您处于用户模式并尝试访问受内核保护的页面,则会触发故障。如果您尝试写入只读页面,则会触发错误。如果您尝试执行不可执行的页面,则会触发错误。

这是一个相当长的话题。如果您想了解有关该主题的更多信息,则需要了解逻辑内存翻译(有时候称为虚拟内存)。