【问题标题】:Delete a map<int,list<struct*>>删除地图<int,list<struct*>>
【发布时间】:2018-12-04 23:00:04
【问题描述】:

伙计们,我在实现具有 map&lt;int,list&lt;Arestas*&gt;&gt;. 的类的析构函数时遇到问题

以这张地图为例:

我的地图将如下所示:

key   list  
[1] - [2,10] -> [3,100] -> [4,25]  
[2] - [1,10] -> [3,50]  
[3] - [2,50] -> [1,100] -> [4,40]  
[4] - [1,25] -> [3,40] 

我的 Arestas 课程包含:

class Arestas {
private:
    Fronteira *vertice;
    unsigned int custo;
}

我的析构函数现在看起来像这样:

for (auto it = myGrafo.begin(); it != myGrafo.end(); ++it) {
    for (auto it1 = (*it).second.begin(); it1 != (*it).second.end(); ++it1) {
        delete *it1;
    }
    (*it).second.clear();
}  

但是当我从 key[2] 获取列表时给我这个错误:

_CRT_SECURITYCRITICAL_ATTRIBUTE
void __CRTDECL operator delete(void* const block) noexcept
{
    #ifdef _DEBUG
    _free_dbg(block, _UNKNOWN_BLOCK);
    #else
    free(block);
    #endif
}  

提前谢谢你!

编辑 我在我的地图中插入Arestas*,如下所示:

Arestas *aux = new Arestas();
        aux->setCusto(_custo);
        aux->setVertice(encontrarFronteira(vertice_destino));
        // Se o vertice nao existir
        if (aux->getVertice()->getVertice() == NULL) {
            cout << "ERROR" << endl;
            exit(1);
        }
        myGrafo[vertice_origem].push_back(aux);

        // Put the same path in the opposite vertice
        Arestas *aux1 = new Arestas();
        // set cost
        aux1->setCusto(_custo);
        // it looks for the vertice in the list<vertices*>
        aux1->setVertice(encontrarFronteira(vertice_origem));
        myGrafo[vertice_destino].push_back(aux1);

【问题讨论】:

  • 需要更多数据。发生了一些不好的事情,但它可能发生在很久以前,程序实际上只是在析构函数期间才意识到它。例如,Rule of Three 违规会导致双重删除。问题:您有充分的理由将Arestas* 存储在列表中吗?消除指针应该会使破坏问题变得毫无意义。
  • 是@AdamZahran,感谢大家,我已经解决了这个问题!谢谢!
  • @user4581301 感谢所有提示,从现在开始我会更加关注三法则!
  • 查看评论 2。它还要求提供 MCVE,并建议您删除图像。请注意,没有一个答案真正直接回答了您的问题。他们主要建议您查看的地方,因为问题无法按照书面形式正确回答。
  • 我们不会对你投反对票,至少我希望人们不会。我们正在否决这个问题。好的(完整的和原创的)问题通常会得到支持。边缘问题通常会被搁置,不好的问题会被否决。看起来这个有一个反对票和两个近距离投票。这还不算太糟糕,真的。有些下降到 -10 并在一分钟内关闭并删除,但这些通常是 Gimmie teh coedz!!! 问题或每天重复多次的问题,例如,为什么@987654332 @ 不等于 3?。你提供了足够好的指导猜测并得到了答案。这是一场胜利。

标签: c++ dictionary pointers memory memory-management


【解决方案1】:

您似乎对建筑物的所有权有疑问。您的列表中多次出现这些 aresta,并且多次删除它们是未定义的行为,因此您只需删除它们一次。

试试这样的:

std::set<Arestas*> s;

for(const auto& p1: m)
{
    for(const auto& el: p1.second)
    {
        s.insert(el);
    }
}

因此,您创建了一组需要删除的所有元素。然后删除它们(也适用于唯一指针,实际上是更好的解决方案)。

for(auto p: s)
{
    delete p;
}

看来您的 Arestas 可能是独一无二的,所以如果 vertice 在那里共享和销毁,问题可能出在 Arestas 析构函数上。

【讨论】:

  • 如何保证Arestas 指针在该集合中的唯一性?如果两个指针指向同一个对象,它们就不一样了,集合仍然会把它们放进去。
  • 是的,vertice 在所有Arestas* 中都是相同的,例如 [3,100] 和 [3,50]。这就是问题所在,我想知道删除地图后是否可以删除所有顶点。我不知道我是否说清楚了。
  • 感谢 Matthieu,在查看了我的代码后,问题出在 Arestas 析构函数上。
  • 在给出的示例中,列表之间没有共同点。
  • 好的@LightnessRacesinOrbit 我不知道该说什么,你在stackoverflow 中的第一个问题怎么样?你有没有像你这样的人在所有的 cmets 中都说你做了一个糟糕的问题?即使是强硬的很多人都得到了正确的答案?
【解决方案2】:

首先,您只能使用delete 先前使用new 语句创建的对象。

如果是这样,为了避免多次调用删除,你可以使用像std::shared_ptr&lt;Aresta&gt;这样的智能指针。

您可以使用 Valgrind 执行您的代码以更具体地跟踪此问题。

【讨论】:

  • 您好,谢谢您的帮助。我不确定我是否可以使用这个智能指针,因为我正在为我的 OOP 类做这个项目。而且因为我从来没有在课堂上学过它,所以我不能使用它。
  • 你也在用 new 创建vertice 吗?
  • 多次释放不太可能是问题,因为地图上的所有列表元素都是唯一的。可能性包括从不动态分配,但我们根本没有足够的信息知道。
  • @LightnessRacesinOrbit 是的,很抱歉缺少信息,但由于是一个学校项目,我无法真正发布我所有的代码。但问题出在Aresta 的析构函数中。谢谢!
  • @diogofalken 您需要有一些方法来了解您的对象何时拥有以及何时不拥有。一种可能性是在对象中有一个链接计数。删除链接时,请减少链接计数。如果链接计数达到零,则删除该对象。这可以通过让链接成为一个对象,其构造函数递增计数而析构函数递减计数,从而变得优雅。
猜你喜欢
  • 1970-01-01
  • 2016-07-02
  • 1970-01-01
  • 2012-09-28
  • 1970-01-01
  • 1970-01-01
  • 2015-09-22
  • 2014-06-28
  • 2012-06-07
相关资源
最近更新 更多