You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

循环内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

问题分析

  1. 野指针操作:构造函数中Node* previousNode = previousNode;是将未初始化的指针赋值给自己,导致previousNode为野指针。后续通过该指针调用setAddress会非法修改内存,破坏链表结构,直接引发段错误。
  2. malloc与C++构造函数混用:malloc仅分配内存,不会调用类的构造函数。通过*firstNode = Node(...)的临时对象拷贝方式,虽然能运行,但不符合C++规范,且在类包含复杂成员时会出错。
  3. 无效的container节点:container是malloc分配的未初始化节点,所有节点初始nextNode都指向它,导致链表末尾逻辑混乱。
  4. 尾节点未正确连接:循环结束后,最后一个中间节点的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 01:54:51