【问题标题】:Unhlandled exception due to bad pointer usage由于错误的指针使用导致未处理的异常
【发布时间】:2015-07-09 12:54:14
【问题描述】:

这是我在这里的第一个问题,因此对于您在我的帖子中可能发现的最终正式错误,我深表歉意。

我正在为“无向连接加权图”编写一个简单的类,它必须使用基于向量的邻接表。

问题是,当我从 Eclipse 运行程序时,MS Windows 说它“停止工作”,调试后我收到“0x00AE251A 处的未处理异常 .... 访问冲突写入位置 ...”消息。 环顾四周,我发现这个问题可能是由于缺少指针破坏或指针初始化(?)引起的。我从标准指针切换到 shared_ptr 来解决这个问题,但错误是一样的......

有人可以告诉我吗?我几乎浪费了一整天的时间试图找到原因,但没有成功。

class UndirectedGraph
{
private:
    int V;                                  
    std::vector<std::shared_ptr<std::pair<int,int>>>* adj;    
public:
    UndirectedGraph(int V)
{
        this->V = V;
        this->adj = new std::vector<std::shared_ptr<std::pair<int,int>>>;
}

void addEdge(int v, int w, int weight)
{
    auto sp = std::make_shared<std::pair<int,int>>(std::make_pair(v,weight));
    adj[v].push_back(sp);
}

int main()
{
    UndirectedGraph G1(7);//Ok
    G1.addEdge(0,1,9);//Ok
    G1.addEdge(1,2,5);//Ok
    G1.addEdge(2,0,8);//EXCEPTION RAISED HERE (if line is commented all run fine)
    return 0;
}

【问题讨论】:

  • 您没有在构造函数中使用 V 参数,因此当您尝试 adj[v].push_back(sp); 时,您的向量 this->adj 为空
  • 即使我在“adj”初始化的末尾添加 (V) 作为大小,问题仍然存在。另外,我认为即使向量为空,push_back 也应该可以工作,对吧?

标签: c++ graph memory-leaks shared-ptr digraphs


【解决方案1】:

我注意到代码中有几个错误:

  1. 如果您需要的是邻接列表,那么this-&gt;adj 应该是向量的向量。目前,它只是&lt;int,int&gt; 对的一维向量。相反,它应该是:

    std::vector&lt;std::vector&lt;std::shared_ptr&lt;std::pair&lt;int,int&gt;&gt;&gt;&gt;* adj;

  2. 在构造函数中,this->adj应该初始化如下:

    this-&gt;adj = new std::vector&lt;std::vector&lt;std::shared_ptr&lt;std::pair&lt;int,int&gt;&gt;&gt;&gt;(V);

  3. 现在,在 addEdge 函数中,您需要先访问与节点 'v' 对应的向量,然后将 (w, weight) 对推入该向量中 [注意也就是说,即使我们忽略只有向量的错误,逻辑仍然不正确,因为您将 (v, weight) 而不是 (w, weight) 推入那个向量]。修改后的 addEdge 函数是这样的:

    void addEdge(int v, int w, int weight)
    {
        auto adjacencyList = adj->at(v);
        auto sp = std::make_shared<std::pair<int,int>>(std::make_pair(w,weight));
        adjacencyList.push_back(sp);
    }
    

希望对你有帮助

【讨论】:

  • 感谢您的回答@jithinpt!结构合理,解释清楚。我是 C++ 的新手,我有点困惑。你能告诉我使用这样的指针定义 2D LinkedList 的优势吗:std::list&lt;int&gt;* adj= new std::list&lt;int&gt;[V]; 而不是简单地这样做:std::list&lt;int&gt; adj= new std::list&lt;int&gt;[V]; 谢谢!
  • @mitxael:只有第一个有效。如果你尝试第二种方法,你会得到一个编译器错误。简要说明为什么会这样:有两种分配任何对象的方法(列表、向量等)。您可以在堆栈或堆上分配它。当您使用“new”关键字创建对象时,该对象会在堆上分配空间,并为您提供指向该空间的“指针”。这就是在定义返回类型时必须使用“*”的原因(例如:list * adj)。要在堆栈上分配,您只需将其声明为 std::list adj.
  • 上一个回复很简短,因为字数限制。这篇 SO 帖子可能有助于进一步澄清您的疑问:stackoverflow.com/questions/8036474/…
  • 另一个可能有帮助的帖子:stackoverflow.com/questions/599308/…
猜你喜欢
  • 2015-12-11
  • 2016-08-27
  • 1970-01-01
  • 2023-03-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多