首页 > 解决方案 > 如何在不导致分段错误的情况下删除堆上的对象

问题描述

嗨(我是一个试图学习的 C++ 学生,请不要在高级阶段烤我),

我在temArr堆上创建了对象。我的程序在我运行它时编译没有问题,但没有删除temArr堆上的内容,但是当我通过 valgrind 运行它时,在 temArr 上存在内存泄漏。但是当我用delete temArr; temArr = nullptr;. 我得到一个分段错误。

我试图在堆栈上进行此操作: NodeList* n1(0); n1 = temArr; return n1->getNode(Index);< 这有效,但何时delete temArr; temArr = nullptr;返回不正确的随机变量。

有没有办法我可以将堆上的值放入堆栈删除堆然后返回堆栈上的对象?或者我是在删除我的堆错误,因此它给出了分段错误?

代码 :

Node *PathSolver::findShortDis(NodeList *openList, Node *nodeG, NodeList *closeList) {

    int Index =0;
    
    NodeList* temArr = new NodeList();
    
    for (int x = 0; x < openList->getLength(); x++) {
        if (closeListCheck(openList->getNode(x), closeList)) {
            temArr->addElement(openList->getNode(x));
        }
    }
    //assign tem to the very first node of temA
    int tem = temArr->getNode(0)->getEstimatedDist2Goal(nodeG);

    //compare
    for (int x = 0; x < temArr->getLength(); x++) {
        if (temArr->getNode(x)->getEstimatedDist2Goal(nodeG) <= tem) {
            tem = temArr->getNode(x)->getEstimatedDist2Goal(nodeG);
            Index = x;
        }
    }

    for(int x = 0; x <  temArr->getLength(); x++) {
        if (openList->getNode(x)->getCol() == temArr->getNode(Index)->getCol()
        && openList->getNode(x)->getRow() == temArr->getNode(Index)->getRow()){
            Index = x;
        }
    }

    // NodeList* n1(0);
    // n1 = temArr;
    // return n1->getNode(Index);

    // delete temArr;
    // temArr = nullptr;

    return temArr->getNode(Index);

}

提前谢谢你。

标签: c++memory-leaksstackc++14heap-memory

解决方案


如果您取消注释您的delete temArr行,则您的return语句正在尝试访问temArr变量,之后它已被延迟。这是未定义的行为,任何事情都可能发生,从获取随机值到段错误。

temArr不需要动态分配,只需在堆栈上创建它,有一个问题是,在你被删除Node*后你返回的指针会发生什么NodeList,但我们不能在没有看到其余代码的情况下说。

调用成员函数时,您必须将所有->运算符更改为。.

NodeList temArr{}; // Create NodeList on the stack
.
.
.
return temArr.getNode(index);

您还可以将要返回的值存储在一边,删除对象然后返回。

Node* returnValue = temArr->getNode(Index);
delete temArr;
return returnValue;

或者使用智能指针,它将动态分配对象,但在离开范围时将其删除。

std::unique_ptr<NodeList> temArr = std::make_unique<NodeList>();
.
.
.
return temArr->getNode(index);

temArr在堆栈上创建(第一个代码)是最简单/最好的解决方案,但在所有 3 种情况下,请确保该方法返回的值在被删除getNode是有效的。NodeList


推荐阅读