C语言链表实现字符串遇长输入malloc崩溃问题求助
问题根源与修复方案
1. 核心崩溃原因:输入缓冲区溢出
你的main函数中,仅为输入字符串分配了1字节的内存:
char *a = (char*) malloc(sizeof(char));
但使用scanf("%[^\n]",a)读取输入时,会将所有换行前的字符写入a指向的内存,完全不考虑分配的空间大小。短输入时可能刚好没破坏堆的关键结构,暂时能运行;长输入会直接越界写入,破坏堆的管理信息,导致后续调用malloc时触发崩溃——这就是为什么首次malloc就出错的原因。
2. 其他代码问题
- 变量名不匹配:
main中定义的链表头是list,但调用makeString时传的是&string,string未定义,编译会报错,属于笔误。 - 未检查
malloc返回值:无论是分配输入缓冲区还是链表节点,都没有判断malloc是否成功,内存不足时会引发未定义行为。 - 插入效率低下:
insert函数每次都从链表头遍历到尾部插入新节点,长链表时时间复杂度为O(n²),可以通过维护尾指针优化。
修复后的代码示例
#include <stdio.h> #include <stdlib.h> #include <string.h> struct Map { char val; struct Map *next; }; // 优化:添加尾指针,避免每次遍历链表尾部 void insert(struct Map **head, struct Map **tail, char value){ printf("%c", value); struct Map *New = (struct Map *)malloc(sizeof(struct Map)); if (New == NULL) { // 检查malloc是否成功 perror("malloc failed"); exit(EXIT_FAILURE); } New->val = value; New->next = NULL; if ((*head) == NULL) { *head = New; *tail = New; } else { (*tail)->next = New; *tail = New; } } void makeString(struct Map **head, struct Map **tail, char *needStr){ int i = 0; while (needStr[i] != '\0'){ insert(head, tail, needStr[i]); i++; } } int main() { struct Map *list = NULL; struct Map *tail = NULL; // 使用固定大小缓冲区,或根据需求调整,也可使用getline实现动态扩容 char buf[1024]; if (fgets(buf, sizeof(buf), stdin) == NULL) { perror("fgets failed"); return 1; } // 移除fgets读取到的换行符 buf[strcspn(buf, "\n")] = '\0'; makeString(&list, &tail, buf); // 释放链表内存,避免泄漏 struct Map *tmp; while (list != NULL) { tmp = list; list = list->next; free(tmp); } return 0; }
额外建议
- 优先使用
fgets代替scanf("%[^\n]"),fgets可以限制读取的字符数,从根源避免缓冲区溢出。如果需要支持任意长度输入,可使用POSIX标准的getline函数实现动态扩容。 - 所有动态内存分配操作后,必须检查返回值是否为
NULL,避免空指针访问引发崩溃。 - 链表使用完成后记得遍历释放所有节点,避免内存泄漏。
内容的提问来源于stack exchange,提问作者huntrese
相关产品推荐
相关产品推荐

