Search code examples
c++segmentation-faultboost-graph

C++ boost graph library segmentation fault with adjacency_iterator


I am trying to make a class called GraphService with the Boost Graph Library. It should compute various stuff on graphs and return properties like the node degree distribution to other classes. This is a part of my headerfile for the graph, which is called Graph.h:

typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS,
                          vertex_info, edge_info, graph_info, boost::listS> Graph;
typedef boost::graph_traits<Graph>::vertex_descriptor VertexDescriptor;
typedef boost::graph_traits<Graph>::edge_descriptor EdgeDescriptor;
typedef boost::graph_traits<Graph>::vertex_iterator VertexIterator;
typedef boost::graph_traits<Graph>::edge_iterator EdgeIterator;
typedef boost::graph_traits<Graph>::adjacency_iterator AdjacencyIterator;

And this is a part of my Headerfile for GraphService:

#include "Graph.h"
class GraphService {
    private:
        Graph g;
    public:
        std::vector<int> get_adjacent(int i);
}

The part that is troubling me, is this:

#include "Graph.h"

GraphService::GraphService(Graph graph) {
g = graph
}



std::vector<int> GraphService::get_adjacent(int i) {
    AdjacencyIterator first, last;
    std::vector<int> vertex_vector;
    vertex_vector.push_back(i);

    for (tie(first,last) = adjacent_vertices(i,g); first != last; ++first) {

        vertex_vector.push_back(g[*first].id);
    }

    return vertex_vector;
}

I tested this function with UnitTests and the tests work correctly, but in my compiler output, I see the following error-message;

/bin/sh: line 7: 20148 Segmentation fault      build/Debug/GNU-Linux-x86/tests/TestFiles/f2

This seems to refer to fault with the adjacency_iterator. The Debugger tells me, that the error occurs, because of the iterator last.

I have tried to run the same code in a script where the creation of the graph and the iteration over adjacent_vertices are in the same function. Everything works correctly there.

Can anyone help?

Thanks in advance!


Solution

  • I agree, especially in relation to your previous question, you probably have errors (Undefined Behaviour?) outside the code shown.

    The code shown could just work, see this SSCCE:

    Live On Coliru

    #include <boost/graph/adjacency_list.hpp>
    #include <boost/multi_array.hpp>
    
    using namespace boost;
    
    struct vertex_info {
        int id = []{ static int s_gen = 0; return ++s_gen; }();
    };
    
    struct edge_info {
    };
    
    struct graph_info {
    };
    
    typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS, vertex_info, edge_info, graph_info, boost::listS>
        Graph;
    typedef boost::graph_traits<Graph>::vertex_descriptor VertexDescriptor;
    typedef boost::graph_traits<Graph>::edge_descriptor EdgeDescriptor;
    typedef boost::graph_traits<Graph>::vertex_iterator VertexIterator;
    typedef boost::graph_traits<Graph>::edge_iterator EdgeIterator;
    typedef boost::graph_traits<Graph>::adjacency_iterator AdjacencyIterator;
    typedef multi_array<int, 3> array3i;
    
    class GraphService {
      private:
        Graph g;
    
      public:
        GraphService(Graph graph) { g = graph; }
        std::vector<int> get_adjacent(int i);
    };
    
    std::vector<int> GraphService::get_adjacent(int i)
    {
        AdjacencyIterator first, last;
        std::vector<int> vertex_vector;
        vertex_vector.push_back(i);
    
        for (tie(first, last) = adjacent_vertices(i, g); first != last; ++first) {
            vertex_vector.push_back(g[*first].id);
        }
    
        return vertex_vector;
    }
    
    #include <iostream>
    #include <boost/graph/random.hpp>
    #include <random>
    
    int main() {
        std::mt19937 prng { std::random_device{}() };
        Graph example;
        generate_random_graph(example, 100, 200, prng);
    
        GraphService let_clone_that(example);
    
        std::cout << "adjacent to 42: ";
        for(int v: let_clone_that.get_adjacent(42))
            std::cout << v << " ";
    }
    

    Prints, e.g.

    adjacent to 42: 42 71 38 3 14