什么是段错误?
值得注意的是,段错误并不是由直接访问另一个进程的内存引起的(这是我有时候听到的),因为这是不可能的。使用虚拟内存,每个进程都有自己的虚拟地址空间,没有任何指针的值可以访问另一个地址空间。除了共享库可能是相同的物理地址空间被映射到(可能)不同的虚拟地址和内核内存,即使在每个进程中映射方式也相同(为了避免系统调用时刷新TLB,我想)。还有 shmat 等。 - 这些被我计算为“间接”访问。但是,可以检查它们通常远离进程代码,我们通常能够访问它们(这就是它们存在的原因,但以不当的方式访问它们将产生段错误)。
然而,段错误可能发生在以不正确的方式访问我们自己(进程)内存时(例如尝试写入不可写的空间)。但最常见的原因是访问没有映射到物理地址空间的虚拟地址空间的一部分。
所有这些都是关于虚拟内存系统的。
段错误是一种特定类型的错误,由访问“不属于你”的内存引起。这是一个辅助机制,可以防止您破坏内存并引入难以调试的内存错误。每当您遇到段错误时,就知道您正在错用内存——例如访问已经被释放的变量,写入只读内存的一部分等等。在大多数允许您干预内存管理的语言中,段错误本质上是相同的,在C和C ++中的segfaults之间没有原则上的区别。
有许多方式可以获得segfault,至少在低级语言比如C(++).中。一个获得segfault的常见方法是取消引用null指针:
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。