C语言新手链表实现疑问:新节点地址重复原因排查
addNode创建的节点地址相同? 你遇到的问题核心在于局部变量的内存生命周期,咱们一步步拆解清楚:
问题根源:栈内存的复用
你在addNode函数里定义的struct node newnode是栈上的局部变量。栈内存的特性是:函数执行时为局部变量临时分配空间,函数返回后,这块空间就会被操作系统回收并标记为可复用。当你第二次调用addNode时,系统会把之前用过的栈空间再次分配给新的newnode,所以两次的节点地址完全相同。更严重的是,你把这个局部变量的地址赋值给了链表指针(
*nodeptr = &newnode;),这会导致悬空指针——当函数返回后,newnode的内存已经失效,后续再访问这个指针指向的内容属于未定义行为,程序可能崩溃、输出乱码,或者出现其他诡异的问题。从你的调试输出也能直接验证这一点:
第一次调用后,*base被设置为0000007D6EBFF7C0(也就是第一个newnode的地址);第二次调用时,新的newnode地址还是0000007D6EBFF7C0,这正是栈空间被重复利用的直接证据。修正方案:使用动态内存分配
要创建生命周期不受函数调用影响的节点,需要用到堆内存,也就是通过malloc函数来分配内存。修改你的addNode函数如下:void addNode(int value, struct node** base){ // 用malloc在堆上分配节点内存 struct node* newnode = malloc(sizeof(struct node)); // 检查内存分配是否成功(这一步很重要,避免空指针异常) if (newnode == NULL) { printf("Memory allocation failed!\n"); return; } newnode->value = value; newnode->next = NULL; struct node** nodeptr = base; while(*nodeptr != NULL){ nodeptr = &(*nodeptr)->next; } printf("%d :- value\n",value); printf("%p :- base\n",base); printf("%p :- *base\n",*base); printf("%p :- nodeptr\n",nodeptr); printf("%p :- *nodeptr\n",*nodeptr); printf("%p :- nodeaddress\n\n",newnode); *nodeptr = newnode; }这样每次调用
addNode时,malloc都会在堆上分配一块全新的独立内存,节点地址会各不相同,而且这块内存会一直存在,直到你用free手动释放它。额外提醒:记得释放内存避免泄漏
当你不再需要链表时,要遍历链表逐个释放节点,避免内存泄漏:void freeList(struct node** base) { struct node* current = *base; struct node* next; while (current != NULL) { next = current->next; free(current); current = next; } *base = NULL; // 清空指针,避免后续误操作悬空指针 }在
main函数最后调用freeList(&base);即可完成内存清理。
内容的提问来源于stack exchange,提问作者user2139009

