1、 解引用空指针
当尝试解引用一个未初始化或显式设置为 NULL
的指针时,程序会发生段错误。解引用空指针意味着访问不存在的内存或操作系统保护的内存区域。
#include <stdio.h>
int main() {
int *ptr = NULL; // 指针初始化为 NULL
*ptr = 42; // 尝试解引用空指针,导致段错误
return 0;
}
2、 解引用未初始化的指针
如果一个指针声明了但没有初始化,它的值是不可预测的。解引用它会导致段错误,因为它可能指向无效的内存。
#include <stdio.h>
int main() {
int *ptr; // 声明一个指针,但没有初始化
*ptr = 42; // 未定义行为,可能导致段错误
printf("值: %d\n", *ptr); // 可能无法打印,程序可能崩溃
return 0;
}
3、访问超出数组边界的内存
C 和 C++ 不会为数组执行边界检查,因此如果你访问数组分配空间之外的元素,会导致未定义行为,从而导致段错误。
#include <stdio.h>
int main() {
int arr[5]; // 定义一个大小为 5 的整数数组
// 正常访问数组元素
arr[0] = 10;
arr[1] = 20;
arr[2] = 30;
arr[3] = 40;
arr[4] = 50;
// 打印数组内容
for (int i = 0; i < 5; i++) {
printf("arr[%d] = %d\n", i, arr[i]);
}
// 超出数组边界访问(错误)
arr[10] = 42; // 这将导致段错误
return 0;
}
4、修改字符串字面量
在 C 和 C++ 中,字符串字面量通常存储在只读内存中。尝试修改字符串字面量时,会发生段错误。
#include <stdio.h>
int main() {
// 字符串字面量存储在只读内存中
char *str = "Hello, World!";
// 打印原始字符串
printf("Original string: %s\n", str);
// 尝试修改字符串字面量的内容(错误)
str[0] = 'h'; // 这将导致段错误,修改了只读字符串字面量
// 打印修改后的字符串(如果不崩溃的话)
printf("Modified string: %s\n", str);
return 0;
}
5、访问已释放的内存(悬挂指针)
如使用 free()
(C)或 delete
(C++)释放了一个指针,然后尝试访问它指向的内存,就会产生悬挂指针。访问这块内存会导致段错误。
#include <stdio.h>
#include <stdlib.h>
int main() {
// 使用 malloc 分配内存
int *ptr = malloc(sizeof(int)); // 分配一个 int 类型的内存空间
// 检查 malloc 是否成功
if (ptr == NULL) {
printf("Memory allocation failed.\n");
return 1;
}
// 将分配的内存设置为某个值
*ptr = 42;
// 打印值
printf("Value before free: %d\n", *ptr);
// 释放内存
free(ptr);
// 尝试访问已释放的内存(错误)
*ptr = 42; // 这将导致段错误,访问已释放的内存
// 打印修改后的值(如果不崩溃的话)
printf("Value after free: %d\n", *ptr);
return 0;
}
6、栈溢出(深度递归)
如果程序使用了过多的栈空间,尤其是在递归调用或声明了大局部变量时,可能会发生栈溢出,导致段错误。
#include <stdio.h>
void recursiveFunction() {
// 没有终止条件的递归调用
recursiveFunction(); // 这会导致栈溢出,最终导致段错误
}
int main() {
recursiveFunction(); // 调用递归函数
return 0;
}
7、使用未初始化或过小的缓冲区进行 strcpy() 或 strcat()
使用 strcpy()
或 strcat()
函数时,如果没有检查缓冲区大小,可能会发生缓冲区溢出,从而导致段错误。
#include <stdio.h>
#include <string.h>
int main() {
// 定义一个容量为 10 的字符数组
char buffer[10];
// 尝试将一个超过缓冲区容量的字符串复制到 buffer 中
strcpy(buffer, "This is a long string"); // 这将导致缓冲区溢出,通常会引发段错误
printf("Buffer content: %s\n", buffer); // 这行可能永远不会执行
return 0;
}