【问题标题】:How to fix segmentation fault with two-dimensional nested vectors如何使用二维嵌套向量修复分段错误
【发布时间】:2020-02-18 06:35:47
【问题描述】:

我已经从 gitHub 的一个 Adj List 中编写了一个简单的图形 Adj Matrix。

第一个是Adj列表, 其次是Adj矩阵。

第一个效果很好。但第二个与int Num 错误,它表示与第一个int numOfVertices 一样的顶点数。 它像“int Num”一样成为只读变量。它崩溃到 Process finished with exit code 11

我在 wiki 上查找“分段默认值”,有 4 个原因,其中一个是试图修改只读 变量。

然后我在 Adj Matrix 的构造函数中取消对“Num”的修改。效果很好。

但我不知道为什么第一个很好,而第二个却错了?以及如何解决?因为我需要修改Num的值...

调整列表代码

#ifndef ALTHGORITHM_GRAPH_ADJ_LIST_H
#define ALTHGORITHM_GRAPH_ADJ_LIST_H
#include <iostream>
#include <vector>
#include <queue>
namespace graph_adj_list {
    template <class dataType>                                 // Type of data vertex will hold
    class Graph {
        int numOfVertices;                                      // number of vertices.
        struct Vertex;                                          // forward declaration of vertex structure
        struct Node {                                           // linkedlist for mapping edges in the graph
            Vertex * vertexPtr;                                   // points to the vertex to which the edge is adjecent
            Node * next;                                          // points to the next edge belonging to same vertex
        };
        enum visitedState{                                      // Enum representing visited state of vertex
            WHITE,                                                // not yet visited
            GRAY,                                                 // being visited
            BLACK                                                 // visited
        };
        struct Vertex {
            visitedState state;                                   // state of vertex, visited/being visited/done
            dataType data;                                        // the template data
            Node * list;                                          // Pointer to all edges (linkedlist)
        };

        std::vector<Vertex> vertices;                           // vector of all vertices.
  //private methods
        Node * getNode( Vertex * );                             // allocate and initialize a newnode for the adj list.
        void insertAtEnd( Node * & , Vertex * );                // insert at the end of adjacency list of vertex.
        void deleteAllAfter( Node * );                          // delete the adjacency list of the vertex.
  public:
        Graph() = default;                                      // Default constructor
        Graph(std::vector<dataType> &); 
        ~Graph();
}
  template <typename dataType>
    typename Graph<dataType>::Node *
    Graph<dataType>::getNode(Vertex * v)                // allocate and initialize a newnode for the adj list.
    {
        Node * newNode = new Node;
        newNode->vertexPtr = v;
        newNode->next = nullptr;
        return newNode;
    }
  template <typename dataType>
    void Graph<dataType>::insertAtEnd( Node * & node, Vertex * v)  // insert at the end of adjacency list of vertex.
    {
        Node *newNode = getNode(v);
        if ( node == nullptr ) {
            node = newNode;
        } else {
            Node * temp = node;
            while( temp->next != nullptr ) {
                temp = temp->next;
            }
            temp->next = newNode;
        }
    }
    template <typename dataType>
    void Graph<dataType>::deleteAllAfter( Node * node )                  // delete the adjacency list of the vertex.
    {
        Node * nextNode;
        while( node != nullptr ) {
            nextNode = node->next;
            delete(node);
            node = nextNode;
        }
    }


   template <typename dataType>
    Graph<dataType>::Graph(std::vector<dataType> & values)              // Non default constructor, takes a vector of vertices data
            : numOfVertices(values.size()),
              vertices(numOfVertices)
    {
        for ( int i = 0; i < numOfVertices; ++i ) {
            vertices[i].data = values[i];
            vertices[i].list = nullptr;
            vertices[i].state = WHITE;
        }
    }

    template <typename dataType>
    Graph<dataType>::~Graph()
    {
        for( int i = 0; i < numOfVertices; ++i ) {
            deleteAllAfter(vertices[i].list);
        }
    }
} //end of namespace graph

调整矩阵码

#ifndef ALTHGORITHM_GRAPH_ADJ_MATRIX_H
#define ALTHGORITHM_GRAPH_ADJ_MATRIX_H
#include <iostream>
#include <vector>
namespace graph_adj_matrix {
    template<typename T>
    class Graph {
        int Num ;
        enum visitedState {
            NO_VISIT,
            VISITING,
            VISITED
        };
        struct vertex {
            T data;
            visitedState state;
        };

        std::vector<std::vector<int>> Matrix;
        std::vector<vertex> matrix_list;

    public:
        Graph() = default;
        Graph(std::vector<T> &);
        ~Graph();
        void setMatrix(size_t index1, size_t index2);
        void display();
    };


    template<typename T>
    Graph<T>::Graph(std::vector<T> &values) :
                            Num(values.size())
                            ,matrix_list(Num){
        for (typename std::vector<T>::size_type i = 0; i < Num; ++i)
        {
            matrix_list[i].data = values[i];
            matrix_list[i].state = NO_VISIT;
        }
        for (typename std::vector<T>::size_type i = 0; i < Num; ++i)
            for (typename std::vector<T>::size_type j = 0; j < Num; ++j)
                Matrix[i].push_back(0);
    }

    template<typename T>
    void Graph<T>::setMatrix(size_t index1, size_t index2) {
        for (size_t i = 0; i < Num; ++i) {
            if (i == index1 || i == index2) {
                for (size_t j = 0; j < Num; ++j) {
                    if (((i == index1) && (j == index2)) || ((i == index2) && (j == index1))) {
                        Matrix[i][j] = 1;
                        break;
                    }
                }
                break;
            }
        }
    }

    template<typename T>
    void Graph<T>::display() {
        for (size_t i = 0; i < Num; ++i) {
            for (size_t j = 0; j < Num; j++)
                std::cout << Matrix[i][j] << " ";
            std::cout << std::endl;
        }
    }

    template <typename T>
    Graph<T>::~Graph() {}
}
#endif //ALTHGORITHM_GRAPH_ADJ_MATRIX_H

Cpp:

#include "Graph_Adj_List.h"
#include "Graph_Adj_Matrix.h"

int main() {


    std::vector<std::string> myVec{"ABC","DEF","GHI","ZZZ"};


    graph_adj_list::Graph<std::string> myGraph(myVec);



    graph_adj_matrix::Graph<std::string> myGraph_matrix(myVec);



}

我已经调试了程序

    graph_adj_list::Graph<std::string> myGraph(myVec);

运作良好。 但是

    graph_adj_matrix::Graph<std::string> myGraph_matrix(myVec);

停在

#ifndef _LIBCPP_CXX03_LANG

template <class _Tp, class _Allocator>
inline _LIBCPP_INLINE_VISIBILITY
void
vector<_Tp, _Allocator>::push_back(value_type&& __x)
{
    if (this->__end_ < this->__end_cap())
    {
        __RAII_IncreaseAnnotator __annotator(*this);
        __alloc_traits::construct(this->__alloc(),
                                  _VSTD::__to_raw_pointer(this->__end_),
                                  _VSTD::move(__x));
        __annotator.__done();
        ++this->__end_;
    }
    else
        __push_back_slow_path(_VSTD::move(__x));
}

向量标头 Row 从 1635 到 1653 的函数。 调试器报告这个

Exception = EXC_BAD_ACCESS (code=1, address=0x8)
this = {std::_11::vector<int,std::_1::allocator> * |0x0 } NULL

当我进入设置 ```Matrix[i].push_back(0)''' 的主体时,它会崩溃错误的条件。

【问题讨论】:

  • 请附上一个调试器并向我们展示一个堆栈跟踪以及导致崩溃的(您的)代码。
  • 我正在努力。
  • 如果您希望我们调试您的代码,您需要提供minimal reproducible example
  • @jkeys 好的...我做到了..
  • @jkeys 我会按照你说的改变我的程序。

标签: c++ multidimensional-array clion exit-code segment


【解决方案1】:

在对您的代码进行了短暂的尝试之后,以下只是猜测:

进程以退出代码 11 结束

可能意味着您的程序遇到信号 11(SIGSEGV,又名分段错误)

我的猜测:你忘记初始化 Matrix,所以 Matrix[i].push_back(0); 会导致未定义的行为,幸运的是会导致分段错误。

编辑:您可以使用向量构造函数轻松初始化内部向量:std::vector&lt;std::vector&lt;int&gt;&gt;(Num, std::vector&lt;int&gt;(Num));。这将创建一个带有 Num 副本的矢量,该矢量副本带有 Num 整数。

【讨论】:

  • 真的吗?正如你所说,我已经初始化了Matrix,但问题仍然存在。
  • churill +1 用于查找段错误的根本原因。 @Mr.Weson 他是正确的,不初始化 Matrix 会导致段错误,现在通过初始化向量的向量将该概念扩展到另一个维度。有关更多详细信息,请参阅我的答案。请注意,如果您出于某种原因想要拥有一个 3 维数组,例如表示一个单元格在 3d 坐标系中是填充还是未填充,那么您也必须在那里初始化最内部的向量。
  • @churill 是的,你是对的,我对 Matrix 的初始化是错误的,
  • @churill 既然你已经接受了答案,你可以从我的帖子中添加一点关于必须为 n 维向量(其中 n>1)初始化内部向量的内容吗? (希望括号中的内容至少可以为一位痴迷的计算机科学家节省一些焦虑。)
【解决方案2】:

在解决了@churill 提出的问题之后:

我没有编译你的代码,但我认为问题出在以下几行:

Matrix[i][j] = 1;

在这种情况下,Matrix[i]vector&lt;int&gt;,但您从不为其保留容量,因此 Matrix[i][j] 正在写入受保护/未分配的内存,从而导致段错误。

用足够的容量初始化你的“内部”向量(所有Matrix[i]),看看是否能解决你的段错误。

【讨论】:

  • 是的,我通过调试器发现了错误的情况,谢谢
  • 喜剧时间一如既往,请将此问题标记为已解决,并确保为任何帮助过您的人点赞。
  • 好的!我会做的。
猜你喜欢
  • 2013-10-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-01
  • 2012-09-04
  • 1970-01-01
  • 2012-12-22
相关资源
最近更新 更多