链表搜索功能异常:SIGBUS错误与内存泄漏问题排查
C语言链表程序崩溃问题排查与修复
问题现象
编写的C语言链表程序,逻辑参考自公开资源,他人运行正常但本地出现以下问题:
- 程序通过STDIN每行输入单词,运行时提示
Process finished with exit code 138 (interrupted by signal 10: SIGBUS) - 调试发现卡在
search函数的if (strcmp(var->word, searched) == 0)行 - 程序启动后能输出部分内容,随后崩溃,调试显示
temp->word字段内存读取失败:read memory from 0x6c62430000600000 failed (0 of 1 bytes read)
错误根源分析
Delete函数传参错误:Delete函数接收的head是值传递,删除头节点时,修改的是函数内部的局部head变量,而非主函数中的全局head指针。这会导致主函数中的head依然指向已被释放的内存,后续访问(如search、Count)时触发野指针,引发内存访问错误。Free_All函数内存泄漏:
每个节点的word通过malloc分配,但Free_All仅释放节点结构体本身,未释放word指向的内存,造成内存泄漏。Insert函数冗余赋值:new_node->word = strcpy(new_node->word, word);中,strcpy已返回目标指针,此处赋值属于冗余操作。main函数缓冲区溢出风险:
定义的word[20]和to_delete[15]未限制输入长度,若输入超过数组容量会导致缓冲区溢出。
修复方案
1. 修正Delete函数传参方式
将Delete函数的head改为指针的指针,确保修改同步到主函数:
void Delete(struct node** head, char* to_delete) { struct node *temp = *head; struct node *prev = NULL; while(temp != NULL){ if(strcmp(temp->word, to_delete) == 0) { if(prev == NULL){ *head = (*head)->next; free(temp->word); // 先释放word内存 free(temp); return; } else{ prev->next = temp->next; free(temp->word); // 先释放word内存 free(temp); return; } } prev = temp; temp = temp->next; } }
同时在main函数中调用时传入&head:
Delete(&head, to_delete);
2. 完善Free_All函数,释放word内存
void Free_All(struct node* head){ struct node* temp; temp = head; while( temp != NULL ){ head= head->next; free(temp->word); // 释放节点的word内存 free(temp); temp = head; } }
3. 简化Insert函数冗余赋值
将new_node->word = strcpy(new_node->word, word);改为:
strcpy(new_node->word, word);
也可使用strdup简化(POSIX标准,兼容需求可手动实现):
new_node->word = strdup(word);
4. 修复main函数缓冲区溢出风险
修改scanf调用,限制输入长度:
temp = scanf("%19s", word); // word数组长度20,留1位给终止符 // ... scanf("%19s", word); // ... scanf("%14s", to_delete); // to_delete数组长度15,留1位给终止符
修正后的完整代码
#include <stdio.h> #include <stdlib.h> #include <string.h> struct node{ char* word; struct node* next; }; int search(struct node** head, char* searched); void Print(struct node* head); void Free_All(struct node* head); void Insert(struct node** head, char* word); void Delete(struct node** head, char* to_delete); int Count(struct node* head); int main() { static struct node *head = NULL; int temp; char word[20]; for (;;) { temp = scanf("%19s", word); if (strcmp(word, "Print") == 0) { Print(head); } else if (strcmp(word, "Stop") == 0) { break; } else if (temp == EOF) { Free_All(head); return 0; } else { Insert(&head, word); } } scanf("%19s", word); int found = search(&head, word); if (found == 0) { printf("!! ERROR !!"); Free_All(head); // 错误时也要释放内存 return 1; } else { char to_delete[15]; scanf("%14s", to_delete); Delete(&head, to_delete); // DO OTHER STUFF } int count = Count(head); printf("Remaining nodes: %d\n", count); Free_All(head); return 0; // 补充main函数的返回值 } int search(struct node** head, char* searched) { struct node* var = *head; while (var != NULL) { if (strcmp(var->word, searched) == 0) return 1; var = var->next; } return 0; } void Print(struct node* head){ struct node* temp = head; while (temp) { printf("%s \n", temp->word); temp = temp->next; } } void Free_All(struct node* head){ struct node* temp; temp = head; while( temp != NULL ){ head= head->next; free(temp->word); free(temp); temp = head; } } void Insert(struct node** head, char* word) { // Create new node struct node* new_node = (struct node*)malloc(sizeof(struct node)); new_node->word = malloc(strlen(word)+1); strcpy(new_node->word, word); new_node->next = NULL; if (*head == NULL || strcmp((*head)->word, new_node->word) >= 0) { new_node->next = *head; *head = new_node; } else { struct node* temp = *head; while (temp->next != NULL && strcmp(temp->next->word, new_node->word) < 0) { temp = temp->next; } new_node->next = temp->next; temp->next = new_node; } } void Delete(struct node** head, char* to_delete) { struct node *temp = *head; struct node *prev = NULL; while(temp != NULL){ if(strcmp(temp->word, to_delete) == 0) { if(prev == NULL){ *head = (*head)->next; free(temp->word); free(temp); return; } else{ prev->next = temp->next; free(temp->word); free(temp); return; } } prev = temp; temp = temp->next; } } int Count(struct node* head){ int counter = 0; struct node* var = head; while (var != NULL) { counter++; var = var->next; } return counter; }
内容的提问来源于stack exchange,提问作者user19617564
相关产品推荐
相关产品推荐

