C++递归生成链表问题排查:指针引用理解误区
问题根源分析与修复方案
核心问题:栈局部对象的生命周期失效
你写的递归函数里,ListNode newNode {};是栈上的局部变量——函数调用结束时,栈上的局部变量会被立即销毁,内存被操作系统回收复用。这就导致node->next = &newNode;指向的是一块已经失效的内存,也就是「野指针」。
- 第一个节点值正常,是因为
head是在main函数栈上创建的,生命周期还没结束; - 后续节点的
val随机、打印无限循环,都是因为访问了已释放的栈内存:内存被复用后数据乱掉,甚至可能因为指针指向了栈上的其他区域,形成循环引用,导致printList无法终止。
修复方案:改用堆内存分配节点
要让节点在函数调用结束后依然存在,必须用new在堆上分配内存。同时要注意递归终止时,把最后一个节点的next设为nullptr,避免野指针。
修改后的递归函数:
void nodeFromNumber(int& number, ListNode* node) { if (number == 0) { // 递归终止,当前节点的next设为nullptr node->next = nullptr; return; } node->val = number % 10; number /= 10; // 用new在堆上创建新节点,生命周期不受函数栈影响 node->next = new ListNode(); nodeFromNumber(number, node->next); }
完整测试代码
#include <iostream> using namespace std; struct ListNode { int val; ListNode *next; ListNode() : val(0), next(nullptr) {} ListNode(int x) : val(x), next(nullptr) {} ListNode(int x, ListNode *next) : val(x), next(next) {} }; void nodeFromNumber(int& number, ListNode* node) { if (number == 0) { node->next = nullptr; return; } node->val = number % 10; number /= 10; node->next = new ListNode(); nodeFromNumber(number, node->next); } void printList(ListNode* node) { if (node == nullptr) { cout << "\nlist ended"; return; } cout << node->val << " -> "; printList(node->next); } // 新增:释放链表内存,避免内存泄漏 void freeList(ListNode* node) { if (node == nullptr) return; freeList(node->next); delete node; } int main() { int number = 1234; ListNode head{}; nodeFromNumber(number, &head); cout << "生成的链表:\n"; printList(&head); // 记得释放内存 freeList(&head); return 0; }
额外注意事项
- 用
new分配的内存必须用delete释放,否则会造成内存泄漏,上面的freeList函数就是用来递归释放链表节点的; - 如果你不想用递归,也可以用迭代方式生成链表,逻辑更直观,也避免递归深度过大的问题(比如数字特别长时)。
内容的提问来源于stack exchange,提问作者busido
相关产品推荐
相关产品推荐

