C语言向链表末尾添加节点后打印仅重复输出最后一个节点问题求助
问题排查
- 核心触发打印全是最后一个节点的原因:
newNode->url = url仅拷贝了指针地址,没有拷贝字符串内容。如果你调用add_page时,每次都是复用同一个字符数组存储传入的url,所有节点的url指针都会指向同一块内存,后续内存内容被覆盖后,所有节点读取到的url都会是最后一次写入的值。 - 去重逻辑错误:用
==比较字符串,实际对比的是两个指针的内存地址,不是字符串本身的内容,无法正确识别相同内容的不同url指针。 - 内存泄漏:所有
return语句后的free(newNode)都是死代码,永远不会执行,遇到重复url时申请的newNode内存会直接泄漏。 - 去重逻辑遗漏最后一个节点:循环终止条件是
curr->next != NULL,循环只会遍历到倒数第二个节点,不会校验链表最后一个节点的url是否和新节点重复。
修复后代码
#include <string.h> #include <stdlib.h> #include <stdio.h> struct page *add_page (struct page *web, char *url){ // 先做重复校验,确认不存在再申请内存,避免提前申请导致泄漏 struct page *curr = web; while(curr != NULL){ // 用strcmp比较字符串内容 if(strcmp(url, curr->url) == 0){ printf("URL \"%s\" is already on the web\n", url); return web; } curr = curr->next; } // 确认无重复再申请新节点 struct page *newNode = (struct page*) malloc(sizeof(struct page)); if (newNode == NULL) { perror("malloc failed"); return web; } // 申请新内存存储url内容,避免共用同一块地址 newNode->url = (char*)malloc(strlen(url) + 1); if (newNode->url == NULL) { perror("malloc url failed"); free(newNode); return web; } strcpy(newNode->url, url); newNode->next = NULL; if(web == NULL){ web = newNode; }else{ curr = web; while(curr->next != NULL){ curr = curr->next; } curr->next = newNode; } return web; }
额外注意点
- 后续销毁链表时,需要先释放每个节点的
url指针,再释放节点本身,避免二次内存泄漏。 - 如果你的业务场景可以保证传入的
url指针指向的内存永远不会被修改、且生命周期和链表完全一致,可以省去单独申请内存存储url的步骤,只需把字符串比较逻辑替换为strcmp即可。
内容的提问来源于stack exchange,提问作者issoCoder
相关产品推荐
相关产品推荐

