什么是分段错误? C和C++有区别吗?分段错误和悬空指针有什么关系?
原文由 Rajendra Uppal 发布,翻译遵循 CC BY-SA 4.0 许可协议
什么是分段错误? C和C++有区别吗?分段错误和悬空指针有什么关系?
原文由 Rajendra Uppal 发布,翻译遵循 CC BY-SA 4.0 许可协议
当您的程序尝试访问不允许访问的内存时, 会发生 分段错误(有时称为 segfault )。换句话说,当您的程序尝试访问超出操作系统为您的程序设置的边界的内存时。这是导致程序崩溃的常见情况;它经常与一个名为 core 的文件相关。
程序存储器分为不同的段:
当对变量的引用超出该变量所在的段时,或者尝试写入只读段中的位置时,会发生段错误。实际上,段错误几乎通常是由于试图读取或写入不存在的数组成员,在使用它之前未能正确定义指针,或者(在 C 应用程序中)无意中将变量的值用作地址(参见下面的扫描示例)。
* 例如,调用 memset() 会导致程序出现段错误:
memset((char *)0x0, 1, 100);
* 下面的三个示例显示了最常见的与数组相关的段错误:
案例A
/* "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;
案例B
/* Illegal memory access if value of n is not in the range 0, 1, ... 999 */
int n; int foo[1000]; for (int i = 0; i < n ; i++) foo[i] = i;
案例C
/* Illegal memory access because no memory is allocated for foo2 */
float *foo, *foo2; foo = (float*)malloc(1000); foo2[0] = 1.0;
* 另一个导致段错误的典型编程问题是未能正确使用指针。例如,C 函数 scanf() 需要变量的地址作为其第二个参数;因此,以下内容肯定会导致程序因段错误而失败:
int foo = 0; scanf("%d", foo);
/* Note missing & sign ; correct usage would have been &foo */
虽然变量 foo 可以在内存位置 1000 创建,但前面的函数调用会尝试根据 foo 的定义将整数值读入内存位置 0。
当软件试图以未经授权的方式对内存区域进行操作时,就会发生段错误(例如,尝试写入只读位置会导致段错误)。当您的应用程序用完堆栈空间时,可能会发生段错误。这可能是由于您的 shell 将堆栈大小限制设置得太低,而不是您的软件中的错误。
悬空指针 指向不再存在的东西。悬空指针就是一个例子。
char *ptr = NULL;
{
char c;
ptr = &c; //After the block is over, ptr will be a dangling pointer.
}
当块结束时,变量 c 的范围到期。因为它现在指向不存在的东西,所以“ptr”将成为一个悬空指针。
但是当您尝试访问不属于您的内存或尝试写入只读区域时,您会遇到 分段错误。
char *str ="Testing Seg fault.";
*str= "I hate Seg fault :( ";
‘str’ 将被编译器设为常量。当您尝试更新值时,您正在更改只读部分,从而导致分段错误。因此,分段错误和悬空指针之间有明显的区别。
原文由 Dinindu Gunathilaka 发布,翻译遵循 CC BY-SA 4.0 许可协议
3 回答2k 阅读✓ 已解决
2 回答3.9k 阅读✓ 已解决
2 回答3.2k 阅读✓ 已解决
1 回答3.2k 阅读✓ 已解决
1 回答2.7k 阅读✓ 已解决
3 回答3.4k 阅读
1 回答1.6k 阅读✓ 已解决
分段错误是由于访问“不属于您”的内存而导致的一种特定错误。它是一种帮助机制,可防止您破坏内存并引入难以调试的内存错误。每当您遇到段错误时,您就知道您的内存有问题 - 访问已被释放的变量,写入内存的只读部分等。在大多数让您搞砸的语言中,分段错误基本上是相同的对于内存管理,C 和 C++ 中的段错误之间没有主要区别。
有很多方法可以获得段错误,至少在 C(++) 等低级语言中是这样。获取段错误的常见方法是取消引用空指针:
当您尝试写入标记为只读的内存部分时,会发生另一个段错误:
悬空指针指向一个不再存在的东西,就像这里:
指针
p
是因为它指向字符变量c
在块结束后不再存在。当您尝试取消引用悬空指针(如*p='A'
)时,您可能会遇到段错误。