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

用C语言创建链表节点时地址异常问题求助

链表节点地址重复及构建错误的修复方案

问题根源分析

你的代码存在多处逻辑错误,导致出现节点地址看似重复、链表构建失败的问题:

  • 重复分配节点内存:循环内先给newdata分配内存,紧接着调用createNode再次分配,前一次的内存直接泄漏,属于冗余操作。
  • 共享数据内存:仅在循环外分配一次stdinfo内存,每次循环都覆盖该内存的内容,导致所有节点的stdPtr指向同一块地址,看起来像是节点本身地址重复。
  • prev初始化错误:提前malloc节点却立刻赋值为head(初始为NULL),造成内存泄漏,正确做法是直接将prev初始化为NULL。
  • 链表构建逻辑混乱:错误判断prev->link!=NULL才移动prev,导致节点链接逻辑出错,无法形成正确的链式结构。
  • 非法指针转换:打印时直接将NODE*强转为int*取值,这是未定义行为,应该从节点的stdPtr中取出对应的STD结构体再访问数据。

修正后的完整代码

#include <stdio.h>
#include <stdlib.h>

// 补充原代码缺失的STD结构体定义
typedef struct {
    int ID;
    int grade;
} STD;

typedef struct node
{
    void* stdPtr;
    struct node* link;
} NODE;

typedef NODE* nodePtr;

NODE* createNode(void* std)
{
    NODE* nodePtr = (NODE*)malloc(sizeof(NODE));
    nodePtr->stdPtr = std;
    nodePtr->link = NULL;
    return nodePtr;
}

int main(void)
{
    FILE* fin = fopen("input.txt", "r");
    if (!fin) {
        perror("无法打开输入文件");
        return 1;
    }
    
    nodePtr head = NULL;
    nodePtr prev = NULL;

    // 读取数据并构建链表
    while (1) {
        // 每次循环分配新的STD内存,保证每个节点数据独立
        STD* stdinfo = (STD*)malloc(sizeof(STD));
        if (!stdinfo) {
            perror("内存分配失败");
            break;
        }

        // 读取数据,失败则释放当前内存并退出循环
        if (fscanf(fin, "%d%d", &stdinfo->ID, &stdinfo->grade) == EOF) {
            free(stdinfo);
            break;
        }

        nodePtr newdata = createNode(stdinfo);
        if (prev == NULL) {
            // 处理第一个节点
            head = newdata;
            prev = newdata;
        } else {
            // 链接新节点并移动prev指针
            prev->link = newdata;
            prev = newdata;
        }

        // 正确打印节点数据
        printf("首节点ID: %d, 当前节点ID: %d\n", 
               ((STD*)head->stdPtr)->ID, 
               ((STD*)prev->stdPtr)->ID);
    }

    // 释放链表内存,避免内存泄漏
    nodePtr current = head;
    while (current != NULL) {
        nodePtr next = current->link;
        free(current->stdPtr);
        free(current);
        current = next;
    }

    fclose(fin);
    return 0;
}

核心修复说明

  1. 独立数据内存:每次循环为stdinfo分配新内存,确保每个节点存储的学生数据互不干扰,解决了所有节点指向同一地址的问题。
  2. 移除冗余内存分配:删除循环内newdata的多余malloc,直接使用createNode返回的指针。
  3. 修正链表构建逻辑:首次创建节点时初始化head,后续直接将prev的link指向新节点,再将prev移动到新节点,形成正确的链式结构。
  4. 增加错误处理:补充文件打开、内存分配失败的判断,提升代码稳定性。
  5. 内存泄漏防护:添加链表内存释放逻辑,避免程序退出后残留内存泄漏。
  6. 正确打印数据:通过节点的stdPtr取出STD结构体,再访问ID和grade字段,避免非法指针转换。

内容的提问来源于stack exchange,提问作者王姿惠

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 01:01:06