什么是分段故障?它在C和C++中不同吗?分段错误和悬挂指针是如何关联的?


当前回答

分段错误是由对进程未在其描述符表中列出的页面的请求,或对进程已列出的页面(例如,只读页面上的写入请求)的无效请求引起的。

悬空指针是指可能指向或不指向有效页,但确实指向“意外”内存段的指针。

其他回答

答案中对“分段错误”有几个很好的解释,但由于分段错误通常会导致内存内容转储,所以我想分享分段错误(核心转储)中“核心转储”部分与内存之间的关系来源:

大约从1955年到1975年,在半导体存储器之前,计算机存储器中的主导技术使用了铜线上的微小磁性甜甜圈。甜甜圈被称为“铁氧体磁芯”,主存储器因此被称为核心存储器或“核心”。

从这里拍摄。

当程序试图访问不存在的内存位置,或试图以不允许的方式访问内存位置时,会发生分段错误或访问冲突。

 /* "Array out of bounds" error 
   valid indices for array foo
   are 0, 1, ... 999 */
   int foo[1000];
   for (int i = 0; i <= 1000 ; i++) 
   foo[i] = i;

这里i[1000]不存在,因此出现segfault。

分段故障的原因:

it arise primarily due to errors in use of pointers for virtual memory addressing, particularly illegal access.

De-referencing NULL pointers – this is special-cased by memory management hardware.

Attempting to access a nonexistent memory address (outside process’s address space).

Attempting to access memory the program does not have rights to (such as kernel structures in process context).

Attempting to write read-only memory (such as code segment).

根据维基百科:

当程序试图访问内存不允许的位置访问或尝试访问内存以不允许的方式定位(例如,尝试写入只读位置,或覆盖操作系统的一部分)。

分段错误是由于访问“不属于您的”内存而导致的一种特定错误。它是一种帮助机制,可以防止损坏内存并引入难以调试的内存错误。每当你得到一个segfault时,你就知道你在内存方面出了问题——访问一个已经被释放的变量,写入内存的只读部分,等等。在大多数语言中,segfault基本上是一样的,这会让你陷入内存管理的困境,在C和C++中segfault之间没有主要区别。

有很多方法可以获得segfault,至少在C(++)等较低级别的语言中是如此。获取segfault的常见方法是取消引用空指针:

int *p = NULL;
*p = 1;

当您尝试写入标记为只读的内存部分时,会发生另一个segfault:

char *str = "Foo"; // Compiler marks the constant string as read-only
*str = 'b'; // Which means this is illegal and results in a segfault

悬挂的指针指向一个不再存在的东西,如下图所示:

char *p = NULL;
{
    char c;
    p = &c;
}
// Now p is dangling

指针p摆动,因为它指向在块结束后不存在的字符变量c。当您尝试取消引用悬空指针(如*p='A')时,可能会得到一个segfault。

简单地说:分段故障是操作系统向程序发送信号表示已检测到非法内存访问,并正在提前终止程序以防止防止内存损坏。