用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; }
核心修复说明
- 独立数据内存:每次循环为
stdinfo分配新内存,确保每个节点存储的学生数据互不干扰,解决了所有节点指向同一地址的问题。 - 移除冗余内存分配:删除循环内
newdata的多余malloc,直接使用createNode返回的指针。 - 修正链表构建逻辑:首次创建节点时初始化head,后续直接将prev的link指向新节点,再将prev移动到新节点,形成正确的链式结构。
- 增加错误处理:补充文件打开、内存分配失败的判断,提升代码稳定性。
- 内存泄漏防护:添加链表内存释放逻辑,避免程序退出后残留内存泄漏。
- 正确打印数据:通过节点的
stdPtr取出STD结构体,再访问ID和grade字段,避免非法指针转换。
内容的提问来源于stack exchange,提问作者王姿惠
相关产品推荐
相关产品推荐

