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


当前回答

老实说,正如其他海报所提到的那样,维基百科在这方面有一篇很好的文章,所以看看吧。这种类型的错误非常常见,通常称为其他错误,如访问违规或一般保护故障。

它们在C、C++或任何其他允许指针的语言中都没有区别。这些类型的错误通常由以下指针引起:

在正确初始化之前使用在它们指向的内存被重新定位或删除后使用。在索引超出数组边界的索引数组中使用。这通常只在对传统数组或c字符串进行指针计算时发生,而不是基于STL/Boost的集合(在c++中)

其他回答

值得注意的是,分段错误不是由直接访问另一个进程内存引起的(这是我有时听到的),因为这根本不可能。对于虚拟内存,每个进程都有自己的虚拟地址空间,无法使用任何指针值访问另一个地址空间。例外情况可能是共享库,它们是映射到(可能)不同虚拟地址的相同物理地址空间,内核内存甚至在每个进程中以相同的方式映射(我认为是为了避免系统调用时的TLB刷新)。还有像shmat这样的东西;)-这些就是我所说的“间接”访问。然而,我们可以检查它们通常位于距离过程代码很远的地方,并且我们通常能够访问它们(这就是它们存在的原因,尽管以不正确的方式访问它们会产生分段错误)。

尽管如此,如果以不正确的方式访问我们自己的(进程)内存(例如试图写入不可写空间),可能会发生分段错误。但最常见的原因是访问虚拟地址空间中根本没有映射到物理地址空间的部分。

所有这些都与虚拟内存系统有关。

分段错误的简单含义是,您试图访问一些不属于您的内存。当我们尝试在只读内存位置读取和/或写入任务或尝试释放内存时,会发生分段错误。换句话说,我们可以将其解释为某种内存损坏。

下面我提到了程序员所犯的导致分段错误的常见错误。

以错误的方式使用scanf()(忘记放&)。

int num;
scanf("%d", num);// must use &num instead of num

以错误的方式使用指针。

int *num; 
printf("%d",*num); //*num should be correct as num only
//Unless You can use *num but you have to point this pointer to valid memory address before accessing it.

修改字符串文字(指针尝试写入或修改只读内存。)

char *str;  

//Stored in read only part of data segment
str = "GfG";      

//Problem:  trying to modify read only memory
*(str+1) = 'n';

尝试通过已释放的地址进行访问。

// allocating memory to num 
int* num = malloc(8); 
*num = 100; 

// de-allocated the space allocated to num 
free(num); 

// num is already freed there for it cause segmentation fault
*num = 110; 

堆栈溢出-:堆栈内存不足访问数组超出界限'使用printf()和scanf()时使用错误的格式说明符'

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

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

在计算中,分段故障或访问违规是由具有存储器保护的硬件引起的故障或故障状况,通知操作系统该软件已尝试访问内存的受限区域-维基百科

您可能正在使用错误的数据类型访问计算机内存。您的案例可能如下所示:

#include <stdio.h>

int main(int argc, char *argv[]) {
    
    char A = 'asd';
    puts(A);
    
    return 0;
    
}

“asd”->是一个字符链,而不是单个字符的char数据类型。因此,将其存储为字符会导致分段错误。在错误的位置存储一些数据。

将这个字符串或字符链存储为单个字符是为了在圆孔中插入一个方形钉。

由于信号:分段故障(11)而终止

塞格姆。错误与尝试在水下呼吸是一样的,你的肺不适合这样。为一个整数保留内存,然后尝试将其作为另一种数据类型进行操作,这根本不起作用。

“分段错误”表示您试图访问无法访问的内存。

第一个问题是你的论点。main函数应该是int main(int argc,char*argv[]),在访问argv[1]之前,应该检查argc是否至少为2。

此外,由于要向printf传递一个浮点值(顺便说一句,在传递到printf时,它会转换为双精度),因此应该使用%f格式说明符。%s格式说明符用于字符串(以“\0”结尾的字符数组)。