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; }