首页 > 解决方案 > c ++从2组指针中删除一个指针

问题描述

我有两组指针,我想从中删除某个指针。但它在删除边缘函数的最后一行给了我一个双重免费错误。

我最初怀疑可能是因为set::erase()隐式调用delete,但我阅读了一些文档并发现不会调用析构函数,因为edge_ins它们edge_outs都是指向 Edge 的指针集。

现在我不确定是什么导致第二次调用时出现双重免费错误,set::erase()所以我来这里寻求帮助。

我怀疑这可能是因为指针被视为对象,当我从中删除相同的指针时,root->edge_outs.erase(e)它已经消失了,所以它由于第二次调用 at 而崩溃root->edge_ins.erase(e)。但到目前为止,我找不到任何有用的东西。

边缘删除:

std::set<Edge*>::iterator
SDG::delete_edge(std::set<Edge*>::iterator e)
{
    delete *e;
    (*e)->head->edge_ins.erase(e);
    return (*e)->root->edge_outs.erase(e);
}

可能是相关的,所以我还将添加我如何为 Edge 分配内存。

边缘创建:

Edge&
SDG::edge(Vertex* out, Vertex* in, Edge::Type type)
{
    // 新しいエッジを生成
    Edge* edge = new Edge(type, *out, *in);

    // 頂点からエッジへの参照
    out->add_out(edge);
    in->add_in(edge);

    return *edge;
}

更新:我已经更改了代码,这样我就不会取消引用已删除的对象,但它仍然会给出双重释放错误。

新代码:

SDG::delete_edge(std::set<Edge*>::iterator e)
{
    (*e)->head->rm_in(e);
    (*e)->root->rm_out(e);
    delete *e;
}

标签: c++pointerssetdouble-free

解决方案


问题解决了。

问题是这个delete_edge函数需要一个std::set<Edge*>::iteratorfromedge_outs作为参数。然后继续从另一个集合中删除元素,这edge_ins导致未定义的行为以某种方式导致双重释放。

为了解决这个问题,我从根本上改变了delete_edge函数,这样它就可以Edge*让函数的用户不会感到困惑。

至于返回值,本来是打算edge_outs在程序迭代的时候用来删除元素的。所以我需要一个使用的循环,iterator = edge_outs.erase(iterator)但我也想同时删除相同的元素edge_ins。因此,我想出了一个确保边缘被正确删除的功能,但似乎我在第一次尝试时失败了。

这是该功能的更好版本:

void
SDG::delete_edge(Edge* e)
{
    e->head->edge_ins.erase(e);
    e->root->edge_outs.erase(e);
    delete e;
}

使用此功能时,在修复之前它是这样使用的:

iterator = delete_edge(iterator)

但是当您执行以下操作时,我意识到它在修复后具有相同的效果:

delete_edge(*(iterator++))


推荐阅读