这不是一个东西in C具体来说,它是类 Unix 操作系统中的一个东西。任何非内存安全的语言(可以尝试访问未映射的页面)都可以编译为存在段错误的可执行文件。包括手写汇编或Fortran。但是,是的,C 和 C++ 是两种使用最广泛的非内存安全语言。
是的,这个名字很古老。 Unix 是old并且没有need重命名SIGSEGV
作为当用户空间通过访问未映射的内存而导致 CPU 故障时内核传递的信号。这样做会破坏很多使用该常量的代码,只需将英文文本字符串更改为strerror
/ perror
对于它的“无效页面错误”也不会特别有帮助,尽管可能,因为我认为这些消息已融入 libc 中。但是不同的 libc 版本在转换过程中多年来都会有不同的消息,不值得这么麻烦。
在使用分页的系统中,对硬件页表中“不存在”的页面的任何访问,或者仅在尝试写入或其他情况下可读的页面,都会导致 CPU 发生异常。内核的页面错误异常处理程序检查页面是否should可以访问,如果可以的话,可以从磁盘将其分页,进行写时复制,或者其他什么。 (分别是主要或次要页面错误)。如果不是,则页面错误“无效”,并且内核向进程传递 SIGSEGV 信号。
同样古老的是SIGFPE
(浮点异常)对于一般的算术异常,在大多数机器上默认情况下唯一可能实际出错的异常是整数除法。 (默认的 FP 环境屏蔽了所有 FP 异常,因此它们只是设置粘性标志,而不是在机器代码中引发异常。)POSIX 标准要求 https://pubs.opengroup.org/onlinepubs/009695399/basedefs/signal.h.html如果由于算术异常而要传递信号,则该信号必须是 SIGFPE。
同样,到现在为止SIGSEGV
已标准化POSIX
和其他 Unix 标准,所以在 Unix 早期的时候,任何人could似乎已经改变了,但它早已过去了。
(有些系统还可以提供SIGBUS
对于其他类型的错误地址错误,例如SPARC 上的 Solaris 提供SIGBUS
用于未对齐的访问。)
另请注意,某些其他类型的权限错误会重载到 SIGSEGV 上。例如,尝试执行 x86 等特权指令lgdt
在 Linux 下会产生 SIGSEGV。 (在这种情况下,用户空间实际上会尝试接管仍用于定义 CPU 运行模式的分段机制,例如长模式下的 16 位、32 位和 64 位代码段。)对于未对齐也是如此。 SSE SIMD 指令。所以就是not严格针对无效页面错误。
命名历史?
可执行文件也有像文本和数据这样的“段”,其中 .text 和 .data 部分分别链接。 “堆”过去大多是连续的,在 .data / .bss 之后增长(通过brk
系统调用,之前mmap(MAP_ANONYMOUS)
或者从 /dev/zero 映射页面是一件事),因此即使操作系统开始使用分页而不是 CPU 分段来进行内存保护,“分段错误”一词对于设计者来说也可能并不是毫无意义,因为“分段错误”可执行文件的“仍然映射到进程内存映像中的连续页面范围。
我不知道有关 Unix 信号命名及其在具有或不具有内存保护功能的 PDP-8 和 PDP-11 硬件上的开发的历史细节,尽管显然PDP-11的部分型号 https://en.wikipedia.org/wiki/PDP-11#Unibus_models有某种形式的内存保护,并且甚至虚拟内存 https://en.wikipedia.org/wiki/PDP-11_architecture#Memory_expansion
TL:DR
计算机科学中有两个难题:缓存失效和命名 https://skeptics.stackexchange.com/questions/19836/has-phil-karlton-ever-said-there-are-only-two-hard-things-in-computer-science,以及相差一的错误。