什么是分段故障?它在C和C++中不同吗?分段错误和悬挂指针是如何关联的?
当前回答
考虑以下代码片段,
代码段1
int *number = NULL;
*number = 1;
代码段2
int *number = malloc(sizeof(int));
*number = 1;
如果你问这个问题,我假设你知道函数的含义:malloc()和sizeof()。
既然已经解决了,SNIPET 1将引发分段错误。而SNIPET 2则不会。
原因如下。
代码段1的第一行是创建一个变量(*number)来存储其他变量的地址,但在本例中,它被初始化为NULL。另一方面片段二的第二行是创建相同的变量(*number)来存储另一个的地址,在这种情况下,它被赋予了一个内存地址(因为malloc()是C/C++中的一个函数,它返回计算机的内存地址)
关键是你不能把水放在一个没有买过的碗里,或者一个已经买过但没有授权使用的碗里。当您尝试这样做时,计算机会发出警报,并抛出SegFault错误。
您应该只使用接近低级的语言(如C/C++)来面对这些错误。其他高级语言中有一个抽象,可以确保您不会犯此错误。
同样重要的是要理解分段错误不是特定于语言的。
其他回答
分段错误是由于访问“不属于您的”内存而导致的一种特定错误。它是一种帮助机制,可以防止损坏内存并引入难以调试的内存错误。每当你得到一个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。
根据维基百科:
当程序试图访问内存不允许的位置访问或尝试访问内存以不允许的方式定位(例如,尝试写入只读位置,或覆盖操作系统的一部分)。
当一个进程(正在运行的程序实例)试图访问另一个进程正在使用的只读内存地址或内存范围或访问不存在的内存地址时,会发生分段错误。
seg错误,当类型不匹配时
分段错误的简单含义是,您试图访问一些不属于您的内存。当我们尝试在只读内存位置读取和/或写入任务或尝试释放内存时,会发生分段错误。换句话说,我们可以将其解释为某种内存损坏。
下面我提到了程序员所犯的导致分段错误的常见错误。
以错误的方式使用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()时使用错误的格式说明符'
考虑以下代码片段,
代码段1
int *number = NULL;
*number = 1;
代码段2
int *number = malloc(sizeof(int));
*number = 1;
如果你问这个问题,我假设你知道函数的含义:malloc()和sizeof()。
既然已经解决了,SNIPET 1将引发分段错误。而SNIPET 2则不会。
原因如下。
代码段1的第一行是创建一个变量(*number)来存储其他变量的地址,但在本例中,它被初始化为NULL。另一方面片段二的第二行是创建相同的变量(*number)来存储另一个的地址,在这种情况下,它被赋予了一个内存地址(因为malloc()是C/C++中的一个函数,它返回计算机的内存地址)
关键是你不能把水放在一个没有买过的碗里,或者一个已经买过但没有授权使用的碗里。当您尝试这样做时,计算机会发出警报,并抛出SegFault错误。
您应该只使用接近低级的语言(如C/C++)来面对这些错误。其他高级语言中有一个抽象,可以确保您不会犯此错误。
同样重要的是要理解分段错误不是特定于语言的。