【问题标题】:How to delete object on heap without causing segmentation fault如何在不导致分段错误的情况下删除堆上的对象
【发布时间】:2021-07-03 02:50:25
【问题描述】:

您好(我是一名 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);

}

先谢谢你了。

【问题讨论】:

  • n1 只是指向堆内存中相同位置的指针,删除该内存后自然无法访问它。如果您想将某些内容传输到堆栈,则需要复制实际对象而不是指向它的指针。例如删除之前的const auto result = temArr-&gt;getNode(Index); 并返回result
  • 如果您正在使用生产代码,而不仅仅是为了了解 new/delete,请考虑使用遵循 C++ RAII 指南的 std::unique_ptr(意味着unique_ptr 会自动为你调用delete)。

标签: c++ memory-leaks stack c++14 heap-memory


【解决方案1】:

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

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

在调用成员函数时,您必须将所有 -&gt; 运算符更改为 .

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(第一个代码)是最简单/最好的解决方案,但确保getNode方法返回的值在之后是有效的 strong>NodeList 已被删除,在所有 3 个案例中。

【讨论】:

  • “您的 termarr 不需要动态分配”虽然这在这里可能是正确的,但这是您的假设,对于此答案的未来读者可能不正确。
【解决方案2】:

段错误的原因是您正在尝试访问已删除的内存,换句话说,在行:return temArr-&gt;getNode(Index) 您正在从悬空指针读取。 有几种方法可以解决这个问题,我会建议你最简单的。

您可以直接在堆栈上分配temArr(这是最简单的方法,但如果NodeList 太大就不好了)。 使用此方法,NodeList 对象的析构函数将在函数结束时被调用,资源将被正确释放。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-01-15
    • 2013-04-15
    • 1970-01-01
    • 1970-01-01
    • 2020-03-15
    • 1970-01-01
    • 2014-08-25
    • 1970-01-01
    相关资源
    最近更新 更多