You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

添加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;
}

关键修复点说明

  1. 给name分配内存:在addFirst里,先用strlen(word)+1算出需要的内存大小(+1是为了存字符串末尾的终止符\0),用malloc分配后再用strcpy复制内容。
  2. 检查malloc返回值:动态内存分配可能失败,必须检查是否拿到了有效的内存,不然后续操作空指针会崩溃。
  3. 修正findItem逻辑:先判断传入的链表是否为空,然后遍历每一个节点(包括最后一个),确保不会漏判匹配项。
  4. 简化head初始化:直接把head设为NULL表示空链表,这是链表的标准初始化方式,不用提前分配一个没用的空节点。
  5. 添加内存释放:程序结束前把链表的所有节点和name的内存都释放掉,养成避免内存泄漏的好习惯。

额外小提示

如果你不想手动管理name的内存,也可以把结构体里的char* name改成固定大小的字符数组,比如char name[256];,这样就不用手动malloc和free了,但要注意输入的字符串不能超过数组的长度哦。

记住一个核心原则:指针只是个地址,必须指向一块有效的、可读写的内存区域,才能对它进行读写操作!

内容的提问来源于stack exchange,提问作者Pascal Wigger

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 09:18:05