为什么push_back进入vector <vector <int >>会导致段错误?

时间:2019-09-14 04:09:08

标签: c++ vector segmentation-fault push-back

想构造一个带有邻接表的图,但是当我向vector<vector<int>>中添加元素时出现段错误。 adj.size()打印5,说明已分配了内存,为什么使用addEdge()方法中的段错误?

 #define V 5

    struct Edge {
        int src, dst;
    };

    void addEdge(vector<vector<int>> &adj, int u, int v)
    {
        adj[u].push_back(v);
    }

    void constructGraph(vector<vector<int>> &adj, vector<Edge> &edges)
    {

        for(Edge e : edges)
        {
            addEdge(adj, e.src, e.dst);
        }
    }

    int main()
    {
       vector<vector<int>> adj(V);

       vector<Edge> edges =
        {
            { 0, 1 }, { 1, 2 }, { 2, 0 }, { 2, 1 },
            { 3, 2 }, { 4, 5 }, { 5, 4 }
        };

        constructGraph(adj, edges);

       return 0;
    }

2 个答案:

答案 0 :(得分:2)

void addEdge(vector<vector<int>> &adj, int u, int v)
{
    adj[u].push_back(v);
}

不正确。向量的operator[]()假定提供的索引有效。如果u无效,则行为未定义。

在您的代码中,传递的向量包含五个元素,并且最后一个边位于main()

vector<Edge> edges =
    {
        { 0, 1 }, { 1, 2 }, { 2, 0 }, { 2, 1 },
        { 3, 2 }, { 4, 5 }, { 5, 4 }               // note the last pair here
    };

将导致addEdge()被调用,u的值为5。那是末日。

虽然#define V 6可以解决问题,但是它不能保护addEdge()避免传递错误的u值。相反,我将实现addEdge(),以便按如下所述保护自己免受不良数据的侵害。

void addEdge(vector<vector<int>> &adj, int u, int v)
{
    if (u < 0) return;                   // handle negative u
    if (u >= adj.size()) adj.resize(u);  //   resize if needed
    adj[u].push_back(v);
} 

一种更好的方法是完全避免使用提供的数据(例如edgesmain()中的数据)作为数组索引。

答案 1 :(得分:0)

已解决。感谢此处提供的指导,请仔细阅读有关内容,并了解到c ++语言已内置了针对此类问题的保护。使用.at()方法可以保护程序员免受越界访问。

void addEdge(vector<vector<int>> &adj, int u, int v)
{
    adj.at(u).push_back(v);
}

如果您使用adj.at(u)而不是adj [u],则程序会正常退出

terminate called after throwing an instance of 'std::out_of_range'
  what():  vector::_M_range_check: __n (which is 5) >= this->size() (which is 5)
Aborted (core dumped)