zou*_*oul 621
分段错误是由访问"不属于您"的内存引起的一种特定错误.它是一种帮助机制,可以防止破坏内存并引入难以调试的内存错误.每当你得到一个段错误时,你就知道你正在做一些错误的内存 - 访问已经被释放的变量,写入内存的只读部分等.在大多数语言中,分段错误本质上是相同的,让你搞砸了在内存管理方面,C和C++中的段错误没有主要区别.
有很多方法可以获得段错误,至少在C(++)等低级语言中.获取段错误的常用方法是取消引用空指针:
int *p = NULL;
*p = 1;
Run Code Online (Sandbox Code Playgroud)
当您尝试写入标记为只读的内存部分时,会发生另一个段错误:
char *str = "Foo"; // Compiler marks the constant string as read-only
*str = 'b'; // Which means this is illegal and results in a segfault
Run Code Online (Sandbox Code Playgroud)
悬空指针指向一个不再存在的东西,就像这里:
char *p = NULL;
{
char c;
p = &c;
}
// Now p is dangling
Run Code Online (Sandbox Code Playgroud)
指针p悬空,因为它指向c块结束后不再存在的字符变量.当你试图取消引用悬空指针(如*p='A')时,你可能会得到一个段错误.
kon*_*ski 108
值得注意的是,分段故障不是由直接访问另一个进程内存引起的(这是我有时听到的),因为它根本不可能.对于虚拟内存,每个进程都有自己的虚拟地址空间,并且无法使用任何指针值访问另一个进程.对此的例外可以是共享库,它们是相同的物理地址空间,映射到(可能)不同的虚拟地址和内核内存,甚至在每个进程中以相同的方式映射(以避免系统调用上的TLB刷新,我认为).像shmat这样的东西;) - 这些是我所谓的'间接'访问.但是,可以检查它们通常位于远离过程代码的位置,我们通常能够访问它们(这就是它们存在的原因,但是以不正确的方式访问它们会产生分段错误).
但是,如果以不正确的方式访问我们自己的(进程)内存(例如尝试写入不可写空间),则可能发生分段错误.但最常见的原因是访问虚拟地址空间中未映射到物理地址的部分.
所有这些都与虚拟内存系统有关.
Ign*_*ams 34
分段错误是由对进程未在其描述符表中列出的页面的请求,或对其确实已列出的页面的无效请求(例如,在只读页面上的写入请求)引起的.
悬空指针是一个指针,可能指向或可能不指向有效页面,但确实指向"意外"的内存段.
当进程(正在运行程序的实例)试图访问其他进程正在使用的只读内存地址或内存范围或访问不存在的(无效)内存地址时,会发生分段错误. 悬空引用(指针)问题意味着尝试访问其内容已从内存中删除的对象或变量,例如:
int *arr = new int[20];
delete arr;
cout<<arr[1]; //dangling problem occurs here
Run Code Online (Sandbox Code Playgroud)
维基百科的Segmentation_fault页面有一个非常好的描述,只是指出原因和原因.有关详细说明,请查看Wiki.
在计算中,分段故障(通常缩短为段错误)或访问冲突是由具有内存保护的硬件引发的故障,通知操作系统(OS)存储器访问冲突.
以下是分段故障的一些典型原因:
反过来,这通常是由导致无效内存访问的编程错误引起的:
取消引用或分配未初始化的指针(指向随机存储器地址的野指针)
取消引用或分配释放的指针(悬空指针,指向已释放/取消分配/删除的内存)
缓冲区溢出.
堆栈溢出.
试图执行无法正确编译的程序.(尽管存在编译时错误,一些编译器仍将输出可执行文件.)