循环内malloc分配的内存退出后会销毁吗?C++链表异常排查
C++链表实现的内存访问问题及解决方法
问题描述
作为C++新手,我尝试用类实现链表,在for循环内使用malloc()为第2到倒数第2个节点分配内存。但调用printList()打印时,内存地址发生变化,无法访问之前存储的值;调试发现printList()循环的第二次迭代开始,getValue()函数触发段错误。
相关代码
#include <stdio.h> #include <stdlib.h> class Node{ private: int value; Node* nextNode; public: Node(){ value = 0; } Node(int localValue, Node* localAddress){ value = localValue; nextNode = localAddress; } void setValue(int localValue){ value = localValue; } void setAddress(Node* localAddress){ nextNode = localAddress; } int getValue(){ return value; } Node* getNextNode(){ return nextNode; } }; class linkedList{ private: Node* firstNode; Node* lastNode; int sizeOfNode = sizeof(Node); int lengthOfList = 0; int iter; Node* container = (Node*)malloc(sizeof(Node)); public: linkedList(int sizeOfList, int* localArray){ firstNode = (Node*)malloc(sizeOfNode); *firstNode = Node(localArray[0], container); Node* previousNode = previousNode; lengthOfList ++; for(int i = 1; i < sizeOfList-1; i++){ iter = i; Node* currentNode = (Node*)malloc(sizeOfNode); printf("\n Next Node Location: %p", currentNode); (*previousNode).setAddress(currentNode); printf("\n Current Node Location: %p", (*previousNode).getNextNode()); *currentNode = Node(localArray[i], container); previousNode = currentNode; lengthOfList ++; } iter++; lastNode = (Node*)malloc(sizeOfNode); *lastNode = Node(localArray[iter], container); lengthOfList ++; } void printList(){ Node* currentNode = firstNode; for(int i = 0; i < lengthOfList; i++){ printf("\n%d: %d\n", i, (*currentNode).getValue()); printf("Next Node Location: %p\n", (*currentNode).getNextNode()); currentNode = (*currentNode).getNextNode(); } } }; int main(){ int passedArray[] = {1, 2, 3, 4}; int sizeOfPassedArray = sizeof(passedArray)/sizeof(int); linkedList list1 = linkedList(sizeOfPassedArray, passedArray); list1.printList(); }
运行输出
Next Node Location: 00000261A1E6F940 Current Node Location: 00000261A1E6F940 Next Node Location: 00000261A1E6F700 Current Node Location: 00000261A1E6F700 0: 1 Next Node Location: 00000261A1E6F780 1: 0 Next Node Location: 0000000000000000
问题分析
- 野指针操作:构造函数中
Node* previousNode = previousNode;是将未初始化的指针赋值给自己,导致previousNode为野指针。后续通过该指针调用setAddress会非法修改内存,破坏链表结构,直接引发段错误。 malloc与C++构造函数混用:malloc仅分配内存,不会调用类的构造函数。通过*firstNode = Node(...)的临时对象拷贝方式,虽然能运行,但不符合C++规范,且在类包含复杂成员时会出错。- 无效的
container节点:container是malloc分配的未初始化节点,所有节点初始nextNode都指向它,导致链表末尾逻辑混乱。 - 尾节点未正确连接:循环结束后,最后一个中间节点的
nextNode未指向真正的尾节点lastNode,造成链表断裂。
解决方法
1. 修复指针初始化
将previousNode正确指向第一个节点:
Node* previousNode = firstNode;
2. 用new替代malloc创建节点
C++中创建类对象必须使用new,它会自动调用构造函数,避免内存初始化问题:
// 创建首节点 firstNode = new Node(localArray[0], nullptr); // 循环中创建节点 Node* currentNode = new Node(localArray[i], nullptr); // 创建尾节点 lastNode = new Node(localArray[sizeOfList-1], nullptr);
同时删除无用的container成员,用nullptr标记链表末尾。
3. 正确连接尾节点
循环结束后,将最后一个中间节点的nextNode指向尾节点:
if (previousNode != nullptr) { previousNode->setAddress(lastNode); }
4. 修正循环边界与长度计算
调整循环边界为i < sizeOfList-1(确保尾节点单独处理),或直接遍历所有元素创建节点,避免遗漏。
修正后的完整代码
#include <stdio.h> #include <stdlib.h> class Node{ private: int value; Node* nextNode; public: Node(){ value = 0; nextNode = nullptr; } Node(int localValue, Node* localAddress){ value = localValue; nextNode = localAddress; } void setValue(int localValue){ value = localValue; } void setAddress(Node* localAddress){ nextNode = localAddress; } int getValue(){ return value; } Node* getNextNode(){ return nextNode; } }; class linkedList{ private: Node* firstNode; Node* lastNode; int lengthOfList = 0; public: linkedList(int sizeOfList, int* localArray){ if (sizeOfList <= 0) return; // 创建首节点 firstNode = new Node(localArray[0], nullptr); Node* previousNode = firstNode; lengthOfList++; // 创建中间节点 for(int i = 1; i < sizeOfList - 1; i++){ Node* currentNode = new Node(localArray[i], nullptr); previousNode->setAddress(currentNode); previousNode = currentNode; lengthOfList++; } // 创建尾节点并连接 if (sizeOfList > 1) { lastNode = new Node(localArray[sizeOfList-1], nullptr); previousNode->setAddress(lastNode); lengthOfList++; } else { lastNode = firstNode; } } void printList(){ Node* currentNode = firstNode; int i = 0; while (currentNode != nullptr && i < lengthOfList) { printf("\n%d: %d\n", i, currentNode->getValue()); printf("Next Node Location: %p\n", currentNode->getNextNode()); currentNode = currentNode->getNextNode(); i++; } } // 析构函数,避免内存泄漏 ~linkedList(){ Node* currentNode = firstNode; while (currentNode != nullptr) { Node* temp = currentNode; currentNode = currentNode->getNextNode(); delete temp; } } }; int main(){ int passedArray[] = {1, 2, 3, 4}; int sizeOfPassedArray = sizeof(passedArray)/sizeof(int); linkedList list1(sizeOfPassedArray, passedArray); list1.printList(); return 0; }
内容的提问来源于stack exchange,提问作者Anshumaan Mishra
相关产品推荐
相关产品推荐

