带有指向向量的向量的 Segfault

Posted

技术标签:

【中文标题】带有指向向量的向量的 Segfault【英文标题】:Segfault with vector of pointers to vectors 【发布时间】:2011-08-29 18:49:18 【问题描述】:

我已将问题缩小到这一行:

    indg = nets[i]->adjlist[i].size();   // indg is in a method of the Ensemble class

上面的变量在哪里

    vector<DDNetwork*> nets;    // this vector is in the Ensemble class

    int indg;

    class DDNetwork
    
        friend class Ensemble;
        ...
        public: 
            vector< vector<int> > adjlist;  // the adjacency list of the network
        ...
    ;

我不明白为什么indg = nets[i]-&gt;adjlist[i].size(); 会导致段错误,我有什么遗漏吗?另外,如果您需要更多信息,我可以添加它。

编辑:我刚刚意识到出了什么问题,我对adjlist 使用与nets 相同的索引,这一行

    indg = nets[i]->adjlist[i].size();

应该是:

    indg = nets[i]->adjlist[j].size();

编辑:通过调试器后,我注意到在Ensemble的构造函数中,nets.size() = 10(预期),但是当方法Ensemble::alloc_dev_memory被调用时,nets.size() = 803384(意外),所以我认为JaredPar 的第二个建议可以解释这个问题。以下是将 DDNetwork* 实例添加到 nets 变量的代码:

    Ensemble::Ensemble(int N, float K, int S, bool seedrand, int ltype, int numNets)
    
        this->N = N;
        this->K = K;
        this->S = S;
        this->ltype = ltype;
        this->numNets = numNets;

        if(seedrand)
            srand(time(0));

        nets.resize(numNets);    // make a vector of pointers to DDNetwork
        for(int i=0; i < numNets; ++i)
            nets[i] = new DDNetwork(N,K,S,seedrand,ltype);

        // pre-compute the S^k for k=0,1,...,Kmax
        Spow[0]=1;                  // S^0 = 1
        int k=1;
        while(k <= Kmax*2) 
            Spow[k] = S*Spow[k-1];  // S^k = S*(S^(k-1))
            ++k;
        
    

当我在 main 函数中实例化集成变量时,会调用此构造函数:

    // instantiate ensemble of networks
    Ensemble ens(N, K, S, seed_rand, multiedge, numNets);
    // run_the ensemble one time step
    ens.run_gpu();

然后,Ensemble::run_gpu 调用 Ensemble::alloc_dev_memory,然后当调用 nets[i]-&gt;adjlist[j].size() 时,我收到分段错误。

nets 引用如何未初始化?

【问题讨论】:

添加adjlist的初始化代码。 也许您的i 超出了向量的范围? nets[i] 超出范围,或者nets[i]-&gt;adjlist[i] 超出范围。 就在线路崩溃之前,您可以使用assert(i&lt;nets.size()); assert(i&lt;nets[i]-&gt;adjlist.size()); 找出它是否是这两者之一。 投票关闭为“过于本地化”: OP 解决了他的问题;他们没有将其作为自己的答案提交;问题归结为一个拼写错误,不太可能帮助解决任何一般问题。 【参考方案1】:

问题可能是以下之一

nets[i] 中的 DDNetwork* 引用未初始化,导致访问成员时出现段错误。 nets 的大小和adjlist 的每个实例未保持同步,导致其中一个偏移量无效

您能否发布将DDNetwork* 实例添加到nets 变量中的代码?

【讨论】:

我在阅读您的答案和 cmets 后发现,我在 adjlist 上使用了错误的索引,这导致它超出了范围。 虽然这不是真正的问题,但事实证明,在程序出现段错误之前,nets 向量的大小错误。【参考方案2】:

有两种可能。要么在索引nets[i] 处没有 DDNetwork,要么尚未创建adjlist[i]

要获得向量的方形向量,您需要正确调整它们的大小:

adjlist.resize( MAX );
for (int i = 0; i < MAX; ++i)
  adjlist[i].resize( MAX );

...only 然后你可以索引它们。或者,您可以push_back 正确的值。

另请注意,您对 nets 数组和 adjlist 数组使用 same 索引,不确定这是否是有意的。

【讨论】:

【参考方案3】:

偶然发现segfault的来源,我在做一些粗略的调试,因为GDB没有关于我的main.cpp文件的信息,为了打印出nets.size(),我不得不临时制作@987654322 @public,在这样做之后,我意识到该程序不再出现段错误。我认为这可能与private/public 的区别有关,但是当我移动线路时

public:
    vector<DDNetwork*> nets;
private:

public:
private:
    vector<DDNetwork*> nets;

行,程序仍然没有段错误,所以我尝试将行 vector&lt;DDNetwork*&gt; nets; 移回原来的位置,一直到所有其他方法和成员声明的下方,就在右大括号 @987654328 之前@,然后程序开始像以前一样出现段错误。导致段错误的行 vector&lt;DDNetwork*&gt; nets; 的位置是什么?

【讨论】:

以上是关于带有指向向量的向量的 Segfault的主要内容,如果未能解决你的问题,请参考以下文章

C++,成员函数返回对包含指向 const 对象的指针的向量的 const 引用

指向另一个类 c++ 中对象向量的指针

使用 unordered_map 值初始化指向向量的指针时出错

指向向量中对象的指针有时指向向量中的不同对象

将指向向量向量的指针移动到特定位置

如何创建指向向量的指针向量