C语言链表removeNode返回指针后free触发段错误如何解决
问题原因&修复方案
- 遍历删除逻辑存在空指针访问
removeNode的while循环仅判断了current != NULL就直接执行current = current->next,后续没有判断current是否为空就调用strcmp(current->data, name),当链表遍历到末尾current为NULL时,访问current->data会直接触发段错误。 - 插入存储的名称带前缀,删除时匹配失败
插入节点时直接复制了完整的argv[x](带+前缀,比如+bill),但删除时传入的是argv[x]+1(去掉-前缀的纯名称,比如bill),二者字符串不相等永远匹配不到节点,会导致遍历走到链表末尾触发上述空指针访问。 - 字符串常量被free触发未定义行为
removeNode匹配失败时返回的是字符串常量"error0",但main函数中不管返回值是什么都会执行free(name),free常量区的字符串会触发内存错误。
修复后完整代码
#include <stdio.h> #include <stdlib.h> #include <string.h> struct node { char *data; struct node *next; }; // 补充打印链表函数 void printList(struct node **head) { struct node *current = *head; while (current != NULL) { printf("%s ", current->data); current = current->next; } printf("\n"); } int insert(struct node ** head, char * name) { struct node * newNode = (struct node * ) malloc(sizeof(struct node)); newNode->data = name; newNode->next = NULL; struct node * current = * head; if ( * head == NULL) { * head = newNode; return 1; } while (current->next != NULL) { current = current->next; } current->next = newNode; return 1; } char * removeNode(struct node ** head, char * name) { struct node * current = * head; struct node * previous; if (current == NULL) { return "error0"; } if (strcmp(current->data, name) == 0) { char * data = current->data; * head = current->next; free(current); printf("Removed %s \n", name); return data; } // 修复遍历逻辑,current下一个节点不为空时才进入后续判断 while (current->next != NULL) { previous = current; current = current->next; if (strcmp(current->data, name) == 0) { char * data = current->data; previous->next = current->next; free(current); printf("Removed %s \n", name); return data; } } return "error0"; } int main(int argc, char * argv[]) { printf("Author : Torin Costales \n"); struct node * head = NULL; for (int x = 1; x < argc; x++) { if (argv[x][0] == '+') { // 修复:只复制+后面的纯名称,不保留前缀 char * name = malloc(strlen(argv[x] + 1) + 1); if (name == NULL) return EXIT_FAILURE; strcpy(name, argv[x] + 1); printf("adding %s \n", name); insert( & head, name); printf("List: "); printList( & head); } else if (argv[x][0] == '-') { printf("removing %s \n", argv[x] + 1); char * name = removeNode( & head, argv[x] + 1); // 修复:仅当返回值不是常量error0时才执行free if (strcmp(name, "error0") != 0) { free(name); } else { printf("Remove failed: %s not found\n", argv[x]+1); } printList( & head); } } // 补充:程序退出前释放剩余节点避免内存泄漏 struct node *tmp; while (head != NULL) { tmp = head; head = head->next; free(tmp->data); free(tmp); } return 0; }
内容的提问来源于stack exchange,提问作者Torin Costales
相关产品推荐
相关产品推荐

