添加char*成员后链表程序出现空指针运行时错误,求解决方法
问题分析与修复方案
嘿,我一眼就看到问题所在了——你没有给结构体里的char* name指针分配实际的内存空间,直接用strcpy往空指针里写数据,这必然会触发空指针错误,甚至导致各种诡异的未定义行为(比如你说的每次错误行不一样,这就是未定义行为的典型表现)。下面我帮你拆解所有问题,再给出完整的修复代码:
你代码里的几个关键问题
char* name未分配内存:结构体里的name只是个空指针(或者野指针),strcpy需要把字符串写到一块可写的内存里,但你直接往这个空指针指向的地方写,完全是非法操作,这就是runtime error的根源。findItem的逻辑漏洞:函数开头直接访问nd->val,如果传入的链表是空的(nd为NULL),会直接崩溃;而且循环里没检查最后一个节点的匹配情况,可能漏判。- main里head的初始化错误:你给
head分配了结构体内存,但head->name还是空指针,strcpy(head->name, "")同样会触发空指针引用错误。
修复后的完整代码
#include <stdio.h> #include <cs50.h> #include <string.h> #include <stdlib.h> // 别忘了加malloc需要的头文件! typedef struct node { int val; char* name; struct node *next; } node_t; void addFirst(int value, char* word, node_t** nd) { // 分配新节点内存 node_t * tmp = malloc(sizeof(node_t)); if (tmp == NULL) { // 一定要检查malloc是否成功! fprintf(stderr, "Failed to allocate memory for node\n"); return; } tmp->val = value; // 为name分配内存:字符串长度+1(要存末尾的\0) tmp->name = malloc(strlen(word) + 1); if (tmp->name == NULL) { fprintf(stderr, "Failed to allocate memory for name\n"); free(tmp); // 已经分配的节点要释放,别留内存泄漏 return; } strcpy(tmp->name, word); tmp->next = *nd; *nd = tmp; } int findItem(int value, char* word, node_t *nd) { // 先判断传入的链表是否为空 if (nd == NULL) { return -1; } // 遍历整个链表,包括最后一个节点 while (nd != NULL) { if (nd->val == value && strcmp(word, nd->name) == 0) { return 0; } nd = nd->next; } return -1; } int main (void) { // 直接把head初始化为NULL,表示空链表,不用提前分配空节点 node_t *head = NULL; addFirst(15, "word", &head); addFirst(14,"word2", &head); printf("%i \n", findItem(15, "word", head)); // 好习惯:程序结束前释放链表内存,避免泄漏 node_t *tmp; while (head != NULL) { tmp = head; head = head->next; free(tmp->name); free(tmp); } return 0; }
关键修复点说明
- 给
name分配内存:在addFirst里,先用strlen(word)+1算出需要的内存大小(+1是为了存字符串末尾的终止符\0),用malloc分配后再用strcpy复制内容。 - 检查
malloc返回值:动态内存分配可能失败,必须检查是否拿到了有效的内存,不然后续操作空指针会崩溃。 - 修正
findItem逻辑:先判断传入的链表是否为空,然后遍历每一个节点(包括最后一个),确保不会漏判匹配项。 - 简化head初始化:直接把
head设为NULL表示空链表,这是链表的标准初始化方式,不用提前分配一个没用的空节点。 - 添加内存释放:程序结束前把链表的所有节点和
name的内存都释放掉,养成避免内存泄漏的好习惯。
额外小提示
如果你不想手动管理name的内存,也可以把结构体里的char* name改成固定大小的字符数组,比如char name[256];,这样就不用手动malloc和free了,但要注意输入的字符串不能超过数组的长度哦。
记住一个核心原则:指针只是个地址,必须指向一块有效的、可读写的内存区域,才能对它进行读写操作!
内容的提问来源于stack exchange,提问作者Pascal Wigger
相关产品推荐
相关产品推荐

