C语言中调用free()触发Segmentation Fault段错误的问题求助
问题分析与修复
段错误的根源
你的代码在free(temp)处触发段错误,核心原因是**pop()函数未检查栈是否为空**:当栈为空(top == NULL)时,仍执行item = top->ch,这会直接访问空指针触发段错误(调试器显示free(temp)为错误位置,实际问题出在前面的空指针访问操作)。
同时代码还存在其他逻辑漏洞:
- 若输入字符串中无
c/C,第一个循环会越界访问数组,后续逻辑完全混乱 - 若
c/C后的字符数量多于前面的字符,会反复调用pop()直到栈为空,继续调用就会触发空指针访问 evaluate函数未处理flag != 1的情况,无返回值会导致未定义行为gets()函数不安全,易造成缓冲区溢出
修复后的代码
#include <stdio.h> #include <stdlib.h> #include <string.h> struct stack { char ch; struct stack *prev; } *top = NULL; typedef struct stack st; char pop(); void push(char c); int evaluate(char arr[100]); int main() { char arr[100]; printf("Enter the string to check format of string in wcwR: "); // 用fgets替代不安全的gets,同时处理换行符 fgets(arr, sizeof(arr), stdin); arr[strcspn(arr, "\n")] = '\0'; if (evaluate(arr) == 1) { printf("Entered string is in correct format\n"); } else { printf("Entered string is in wrong format\n"); } return 0; } int evaluate(char arr[100]) { int i; // 先检查字符串中是否存在c/C int has_c = 0; for (i = 0; arr[i] != '\0'; i++) { if (arr[i] == 'c' || arr[i] == 'C') { has_c = 1; break; } } if (!has_c) { return 0; // 无分隔符c/C,直接返回错误 } // 重新遍历到c/C,压栈前面的字符 for (i = 0; arr[i] != 'c' && arr[i] != 'C'; i++) { push(arr[i]); } i++; int j = i; while (arr[j] != '\0') { // 调用pop前检查栈是否为空,若为空说明后面字符过多 char popped = pop(); if (popped == '\0' || arr[j] != popped) { return 0; } j++; } // 最后检查栈是否为空,若不为空说明前面字符过多 return top == NULL ? 1 : 0; } void push(char c) { st *p = (st *)malloc(sizeof(st)); if (!p) { // 检查malloc是否成功 perror("malloc failed"); exit(EXIT_FAILURE); } p->ch = c; p->prev = top; top = p; } char pop() { if (top == NULL) { return '\0'; // 栈为空时返回特殊标记 } st *temp = top; char item = temp->ch; top = top->prev; free(temp); return item; }
自主排查段错误的技巧
- 检查空指针访问:段错误最常见原因是访问空指针,所有涉及指针的操作(如
ptr->member)前,必须先判断ptr != NULL - 启用编译器警告:用
gcc -Wall -Wextra编译代码,编译器会提示很多潜在问题(比如未初始化变量、无返回值的函数) - 使用调试工具:
- 用
gdb调试:编译时加-g参数,运行gdb ./your_program,输入run触发错误,再用backtrace查看调用栈,定位出错的具体位置
- 用
- 边界条件测试:
- 测试极端输入:比如空字符串、无
c/C的字符串、c/C前/后字符数量不匹配的字符串
- 测试极端输入:比如空字符串、无
- 检查内存操作:
- 确保
malloc成功后再使用指针,避免内存分配失败导致的空指针 - 避免重复释放内存,虽然
free(NULL)是安全的,但空指针访问是危险的
- 确保
- 检查数组越界:循环操作数组时,确保索引不超过数组长度,避免越界访问未知内存
内容的提问来源于stack exchange,提问作者Nishu Patel
相关产品推荐
相关产品推荐

