简体   繁体   English

C++ 调试断言失败; 表达式:列表迭代器不兼容

[英]C++ Debug Assertion Failed; Expression: list iterators incompatible

I am fairly new to C++ and I am trying to make sense out of these exhausting error messages so far.我对 C++ 还很陌生,到目前为止,我正试图从这些令人筋疲力尽的错误消息中弄清楚。 I really got stuck in this one and it really makes no sense at all.我真的陷入了这个困境,这真的毫无意义。 The code that I shared below is a part of a personal directed graph header file I was working on.我在下面分享的代码是我正在处理的个人有向图 header 文件的一部分。 I won't be sharing everything since it is sort of long and other parts seems irrelevant to my problem.我不会分享所有内容,因为它有点长,其他部分似乎与我的问题无关。 But if required please specify, I'll share.但如果需要请指定,我会分享。 Now the function below is to assess if a vertex (ie node) is reachable or not from a given root vertex.现在下面的 function 用于评估顶点(即节点)是否可以从给定的根顶点到达。 It employs a Depth First Search defined iteratively in order to do this.它采用迭代定义的深度优先搜索来做到这一点。

The code compiles but I keep getting this error message in the runtime which makes no sense at all since it seems to be caused by pushing an int to an std::stack (when I comment out the line I do this, the code runs).代码可以编译,但我在运行时不断收到此错误消息,这根本没有意义,因为它似乎是由将 int 推送到 std::stack 引起的(当我注释掉我这样做的行时,代码运行) . Such that it->first is an int.这样 it->first 是一个 int。 It is an index in my adjacency list which is of type std::unordered_map and also represents a vertex id.它是我的邻接列表中的一个索引,它的类型为 std::unordered_map 并且还表示一个顶点 ID。

I tried two different things so far.到目前为止,我尝试了两种不同的方法。 I assigned it->first to a separate int id variable and tried to push it that way.我将它->first 分配给一个单独的 int id 变量并尝试以这种方式推送它。 And I tried to change std::stack to std::stack<Vertex> and tried to push vertices instead of ids as ints (and configured the rest of the code accordingly).我尝试将 std::stack 更改为 std::stack<Vertex> 并尝试将顶点而不是 id 作为整数推送(并相应地配置了代码的 rest)。 Nothing worked, I still get the same error.没有任何效果,我仍然得到同样的错误。

I am using Visual Studio 2017 and MSVC compiler.我正在使用 Visual Studio 2017 和 MSVC 编译器。

Vertex Class:顶点 Class:

template <typename T>
class Vertex {

private:
    int id; //Id of the vertex
    double weight; //Weight of the vertex
    T data; //Custom data to be stored inside the vertex

public:
    Vertex() {} //Default constructor. 
    Vertex(int x, double y, T d) : id(x), weight(y), data(d) {} //Constructor with custom data type T
    Vertex(int x, double y) : id(x), weight(y) {} //Alternative constructor without type T, for graph use only
    int getId() { return id; }
    double getWeight() { return weight; }
    T getData() { return data; }
};

DirectedGraph Class (Abstract):有向图 Class(摘要):

template <typename T>
class DirectedGraph {

private:
    std::unordered_map<int, Vertex<T>> vertices; //Stores vertices
    std::unordered_map<int, std::unordered_map<int, double>> adj_list; //Stores the graph in adjacency list format. Inner-most double type variable stores edge weight.
    size_t n_edges; //Stores total number of edges
    size_t n_vertices; //Stores total number of vertices
    int is_acyclic; //Variable to record if the graph is acyclic or not. Convention for this is following, 1: Graph is acyclic, 0: Graph is not acyclic, -1: Not tested yet

public:

    DirectedGraph();
    ~DirectedGraph();

    bool contains(const int&) const; //Returns true if the graph contains the given vertex_id, false otherwise.
    bool adjacent(const int&, const int&); //Returns true if the first vertex is adjacent to the second, false otherwise.

    void addVertex(Vertex<T>&); //Adds the passed in vertex to the graph (with no edges).
    void addEdge(const int&, const int&, const double&); //Adds a weighted edge from the first vertex to the second.

    void removeVertex(const int&); //Removes the given vertex. Should also clear any incident edges.
    void removeEdge(const int&, const int&); //Removes the edge between the two vertices, if it exists.

    size_t inDegree(const int&); //Returns number of edges coming in to a vertex.
    size_t outDegree(const int&); //Returns the number of edges leaving a vertex.
    size_t degree(const int&); //Returns the degree of the vertex (both in edges and out edges).

    size_t numVertices(); //Returns the total number of vertices in the graph.
    size_t numEdges() const; //Returns the total number of edges in the graph.

    std::unordered_map<int, Vertex<T>> getVertices(); //Returns a vector containing all the vertices.
    Vertex<T> getVertex(const int& u_id); //Retruns specified vertex. If vertex doesn't exist, the id and weight of the returned vertex are both -1. 
    double getEdgeWeight(const int& u_id, const int& v_id); //Returns the weight of the specified edge. If the edge doesn't exist, it returns -1.

    std::vector<Vertex<T>> getNeighbours(const int&); //Returns a vector containing all the vertices reachable from the given vertex. The vertex is not considered a neighbour of itself.
    std::vector<Vertex<T>> getSecondOrderNeighbours(const int&); // Returns a vector containing all the second_order_neighbours (i.e., neighbours of neighbours) of the given vertex.
                                                              // A vector cannot be considered a second_order_neighbour of itself.
    bool reachable(const int&, const int&); //Returns true if the second vertex is reachable from the first (can you follow a path of out-edges to get from the first to the second?). Returns false otherwise.
    bool containsCycles(); // Return true if the graph contains cycles (there is a path from any vertices directly/indirectly to itself), false otherwise.

    std::vector<Vertex<T>> depthFirstTraversal(const int&); //Returns the vertices of the graph in the order they are visited in by a depth-first traversal starting at the given vertex.
    std::vector<Vertex<T>> breadthFirstTraversal(const int&); //Returns the vertices of the graph in the order they are visited in by a breadth-first traversal starting at the given vertex.

    /*
     * Following function is an iterative implementation of Dijkstra's SP algorithm.
     * It returns a pair consisting of an array of shortest distances to all other
     * vertices from the given root vertex u_id (vertices are identified via
     * indexes in the array such that shortest distance to vertex i is placed to
     * the i th element in the array), and a "previous vertex" unordered_map. (If
     * you are unsure about what a "previous vertex" list is,
     * see https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm)
     */
    std::pair<int *, std::unordered_map<int, int>> dijkstra(int u_id);
    std::pair<int, std::vector<Vertex<T>>> shortestPath(int u_id, int v_id); //This function finds the shortest path to a single given target vertex (v_id) from a given vertex (u_id) as a pair that contains <distance, path>

    std::vector<std::vector<Vertex<T>>> stronglyConnectedComponents(); //Identifies and returns strongly connected components as a vector of vectors
    std::vector<Vertex<T>> topologicalSort(); //Returns a topologically sorted list of the graph. It requires the graph to be acyclic. If the graph isn't acyclic, it returns an empty vector.


};

reachable() function (the one that I am having the problem with): reachable() function (我遇到问题的那个):

template <typename T>
bool DirectedGraph<T>::reachable(const int& u_id, const int& v_id)
{
    //This function is a Depth First Search Algorithm that halts when latter vertex is found
    //Returns true if v_id is reachable from u_id

    std::stack<int> track; //Stack for DFS
    bool* visited = new bool[numVertices()]{};
    track.push(u_id); 
    while (!track.empty()) 
    {
        bool found = false; 
        auto it = adj_list[track.top()].begin();
        while (it != adj_list[track.top()].end() && !found) 
        {   
            if (!visited[it->first])
            {
                if (it->first == v_id) 
                {
                    delete[] visited;
                    return true; 
                } 
                visited[it->first] = true;
                track.push(it->first);//  <--When I comment out this line, the code runs.
                found = true; 
            }
            ++it;
        }
        if (!found) { track.pop(); } 
    }
    delete[] visited;
    return false;
}

The Complete Error Message:完整的错误信息:

Debug Assertion Failed!调试断言失败!

Filec:\program files(x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.15.26726\include\list Filec:\program files(x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.15.26726\include\list

Line: 240线路:240
Expression: list iterators incompatible表达式:列表迭代器不兼容

The code is comparing incompatible iterators.该代码正在比较不兼容的迭代器。 It is illegal to compare two iterators that come from different container instances.比较来自不同容器实例的两个迭代器是非法的。 The standard says: The domain of == for forward iterators is that of iterators over the same underlying sequence .标准说: 前向迭代器的 == 域是相同底层序列上的迭代器的域

This requirement is not satisfied by the code, where it may iterate over one std::unordered_map<int, double> , and adj_list[track.top()] may be another std::unordered_map<int, double> object.代码不满足此要求, it可能迭代一个std::unordered_map<int, double> ,而adj_list[track.top()]可能是另一个std::unordered_map<int, double> object。 This incompatibility is caused by the changing of the value of track.top() , due to the line:这种不兼容是由track.top()的值的变化引起的,由于以下行:

            track.push(it->first);//  <--When I comment out this line, the code runs.

When not running under debug mode, the code may suddenly start running, since the compiler no longer generates this validation code, but it also may trash your memory and crash in weird ways.当不在debug模式下运行时,代码可能会突然开始运行,因为编译器不再生成此验证代码,但它也可能会破坏您的 memory 并以奇怪的方式崩溃。

The error is quite clear: the code compares iterators that come from different container objects.错误很明显:代码比较了来自不同容器对象的迭代器。 The iterators must come from the same container object.迭代器必须来自同一个容器 object。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM