Pointers 操作系统如何在不检查所有指针地址的情况下确定空指针访问?

Pointers 操作系统如何在不检查所有指针地址的情况下确定空指针访问?,pointers,operating-system,segmentation-fault,signals,memory-segmentation,Pointers,Operating System,Segmentation Fault,Signals,Memory Segmentation,已知0地址(标记为宏“NULL”)不合法访问。 我想知道,操作系统(比如linux)如何确定何时可以访问代码中的某个空地址,而不必访问代码中的每个指针地址? 我认为这与信号有关,特别是“sigsegv”信号 但我不确定它是如何完成的。内存管理单元在取消引用NULL指针或访问无效地址时,在异常触发中起着关键作用 在MMU对每个RAM访问执行的正常虚拟到物理内存映射过程中,在MMU描述符中定义的虚拟地址范围内根本找不到未定义的地址。如果在操作系统内核空间中发生,或者只是在用户空间域中处理kill和c

已知0地址(标记为宏“NULL”)不合法访问。 我想知道,操作系统(比如linux)如何确定何时可以访问代码中的某个空地址,而不必访问代码中的每个指针地址? 我认为这与信号有关,特别是“sigsegv”信号


但我不确定它是如何完成的。

内存管理单元在取消引用
NULL
指针或访问无效地址时,在异常触发中起着关键作用

MMU
对每个
RAM
访问执行的正常虚拟到物理内存映射过程中,在
MMU描述符中定义的虚拟地址范围内根本找不到未定义的地址。如果在操作系统内核空间中发生,或者只是在用户空间域中处理kill和cleanup,这可能会产生灾难性的后果

…操作系统(比如linux)如何确定何时可以访问代码中某个地方的空地址,而不必访问代码中的每个指针地址

好吧,如果不访问指针,操作系统就无法确定空的解引用。对于分段故障,请从中选择:

在计算中,分段故障(通常简称为SEGFULT)或访问冲突是由具有内存保护的硬件引起的故障,通知操作系统(OS)内存访问冲突;在x86计算机上,这是一般保护故障的一种形式。作为响应,OS内核通常会执行一些纠正操作,通常通过向进程发送信号将故障传递给有问题的进程

内存访问冲突是一个运行时事件,除非存在无效访问,否则操作系统将无法向进程发出信号

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

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

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

当您通过指针访问内存时,CPU会查看指针指定的虚拟地址的映射,并检查后面是否有真实的物理内存。根据您正在尝试的操作,将执行其他检查以验证您是否具有对该内存块的读或写访问权限

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


包含
NULL
地址的零页通常故意不映射,因此通常由编程错误导致的空指针访问很容易被捕获。

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

这意味着两件事:

  • 检查所有指针是否为空值没有相关的软件开销
  • 没有精确检查允许的指针值

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

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

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

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

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

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


这是一个相当冗长的话题。如果您想了解有关该主题的更多信息,您需要了解逻辑内存转换(有时错误命名为虚拟内存)。

但是有没有其他方法(除了sigsegv)可以找到空的解除引用?wannabeprogrammer在解除引用之前可能会进行空检查?