Segmentation Fault

I managed to get my code to a nearly-function state, but now I am suffering from an obnoxious segmentation fault. Note that this likely is not related to the millions of pointers bouncing around everywhere, but rather some invalidated pointer by calling an erase() method for graph_map. Either way, I need help rectifying the code. Note that this class is the only one responsible- nothing else in the code has anything to do with this fault.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#include "Graph.h"

Graph::Graph()
    : base_state(2)
{
    //ctor
}

Graph::~Graph()
{
    for(auto p : graph_map)
        delete_vertex(p.first);
    for(auto p : vertex_holder)
        delete_vertex(p);
}

Graph::Graph(const Graph& other)
    : base_state(other.get_base_state())
{
    //copy ctor
}

Graph& Graph::operator=(const Graph& rhs)
{
    if (this == &rhs) return *this; // handle self assignment
    //assignment operator
    return *this;
}

Vertex** Graph::create_vertex()
{
    Vertex * vert = new Vertex;
    vertex_holder.emplace(vert);
    return |
}

void Graph::create_connector(Vertex* vert1, Vertex* vert2)
{
    Connector * connect = new Connector(&vert1,&vert2);
    graph_map.emplace(vert1, connect);
    graph_map.emplace(vert2, connect);
    if(vertex_holder.count(vert1))
        vertex_holder.erase(vert1);
    if(vertex_holder.count(vert2))
        vertex_holder.erase(vert2);
}

void Graph::delete_connector(Connector* connect)
{
    auto * a = connect->vertex_pair.first;
    auto * b = connect->vertex_pair.second;
    auto p = graph_map.equal_range(&**a);
    for(auto iter = p.first; iter != p.second; iter++)
        if(iter->second == connect)
        {
            graph_map.erase(iter);
            break;
        }
    p = graph_map.equal_range(&**b);
    for(auto iter = p.first; iter != p.second; iter++)
        if(iter->second == connect)
        {
            graph_map.erase(iter);
            break;
        }
    if (graph_map.find(*a) == graph_map.end())
        vertex_holder.emplace(*a);
    if (graph_map.find(*b) == graph_map.end())
        vertex_holder.emplace(*b);
    delete &connect;
}

void Graph::delete_vertex(Vertex* vert)
{
    auto test1 = graph_map.find(vert);
    if(test1 == graph_map.end())
    {
        auto test2 = vertex_holder.find(vert);
        if (test2 == vertex_holder.end())
            return;
        vertex_holder.erase(vert);
        delete |
        return;
    }
    auto p = graph_map.equal_range(vert);
    for(auto iter = p.first; iter != p.second;iter++)
        delete_connector(*&iter->second); //Segmentation fault!
    delete |
}

void Graph::coboundary()
{
    for(auto p : graph_map)
        p.second->coboundary(base_state);
    for(auto p : graph_map)
        p.first->set_state(0);
}

void Graph::boundary()
{
    for(auto p : graph_map)
        p.first->boundary(base_state);
    for(auto p : graph_map)
        p.second->set_state(0);
}

Vertex** Graph::find_vertex(std::pair<int,int> coordinates)
{
    Vertex* a;
    for(auto p : graph_map)
        if(p.first->get_coordinates() == coordinates)
            a = p.first;
        else
            a = graph_map.end()->first;
    return &a;
}
70 and 88: What?
114: An end() iterator points outside the container.
Last edited on
Holy three star riot Ispil! That is really something else to read. Could you post "Graphic.h" or link to the Git Hub? I think I have to read the header to figure out a fix, or even to be sure for that matter, but the trouble on Line 87 looks like an operator precedence mix-up, the ampersand and the asterisk are at the same level and so are read processed right to left. So de-referencing the address of something doesn't make a whole lot of sense. EDIT: Are you trying to delete a base pointer or something?

Unless the 'Vertex' and 'Connector' types themselves are pointers then I'm with helios on his comment there. What the heck are you doing?

QUESTION: Should I feel sorry for, or impressed by whoever you are working on this with?
Last edited on
Yes, my silly mistake on 70 and 88. Fixed that up. As for 114, changed it to begin(). Still, this segfault is really frustrating to deal with.

EDIT: Well, I managed to fix one segfault and am now met with another. Here's the new code, with Graph.h as well:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#ifndef GRAPH_H
#define GRAPH_H
#include <unordered_map>
#include <unordered_set>
#include <memory>
#include "Connector.h"
#include "Vertex.h"

class Graph
{
    public:
        Graph();
        ~Graph();
        Graph(const Graph& other);
        Graph& operator=(const Graph& other);
        Vertex** create_vertex();
        void copy_vertex(Vertex&);
        void create_connector(Vertex*,Vertex*);
        void delete_connector(Connector*);
        void delete_vertex(Vertex*);
        void coboundary();
        void boundary();
        unsigned int get_base_state() const {return base_state;}
        Vertex** find_vertex(std::pair<int,int>);
    protected:
    private:
        std::unordered_multimap<Vertex*,Connector*> graph_map;
        std::unordered_set<Vertex*> vertex_holder;
        const unsigned int base_state;
};

#endif // GRAPH_H 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#include "Graph.h"

Graph::Graph()
    : base_state(2)
{
    //ctor
}

Graph::~Graph()
{
    for(auto p : graph_map) //Segmentation fault!
        delete_vertex(p.first);
    for(auto p : vertex_holder)
        delete_vertex(p);
}

Graph::Graph(const Graph& other)
    : base_state(other.get_base_state())
{
    //copy ctor
}

Graph& Graph::operator=(const Graph& rhs)
{
    if (this == &rhs) return *this; // handle self assignment
    //assignment operator
    return *this;
}

Vertex** Graph::create_vertex()
{
    Vertex * vert = new Vertex;
    vertex_holder.emplace(vert);
    return &vert;
}

void Graph::create_connector(Vertex* vert1, Vertex* vert2)
{
    Connector * connect = new Connector(&vert1,&vert2);
    graph_map.emplace(vert1, connect);
    graph_map.emplace(vert2, connect);
    if(vertex_holder.count(vert1))
        vertex_holder.erase(vert1);
    if(vertex_holder.count(vert2))
        vertex_holder.erase(vert2);
}

void Graph::delete_connector(Connector* connect)
{
    if((connect->vertex_pair.first == nullptr)||(connect->vertex_pair.second == nullptr))
        return;
    auto * a = connect->vertex_pair.first;
    auto * b = connect->vertex_pair.second;
    auto p = graph_map.equal_range(&**a);
    for(auto iter = p.first; iter != p.second; iter++)
        if(iter->second == connect)
        {
            graph_map.erase(iter);
            break;
        }
    p = graph_map.equal_range(&**b);
    for(auto iter = p.first; iter != p.second; iter++)
        if(iter->second == connect)
        {
            graph_map.erase(iter);
            break;
        }
    if (graph_map.find(*a) == graph_map.end())
        vertex_holder.emplace(*a);
    if (graph_map.find(*b) == graph_map.end())
        vertex_holder.emplace(*b);
    delete connect;
}

void Graph::delete_vertex(Vertex* vert)
{
    auto test1 = graph_map.find(vert);
    if(test1 == graph_map.end())
    {
        auto test2 = vertex_holder.find(vert);
        if (test2 == vertex_holder.end())
            return;
        vertex_holder.erase(vert);
        delete vert;
        return;
    }
    auto p = graph_map.equal_range(vert);
    for(auto iter = p.first; iter != p.second;iter = p.first)
    {
        delete_connector(*&iter->second);
        p = graph_map.equal_range(vert);
    }
    delete vert;
}

void Graph::coboundary()
{
    for(auto p : graph_map)
        p.second->coboundary(base_state);
    for(auto p : graph_map)
        p.first->set_state(0);
}

void Graph::boundary()
{
    for(auto p : graph_map)
        p.first->boundary(base_state);
    for(auto p : graph_map)
        p.second->set_state(0);
}

Vertex** Graph::find_vertex(std::pair<int,int> coordinates)
{
    Vertex* a;
    for(auto p : graph_map)
        if(p.first->get_coordinates() == coordinates)
            a = p.first;
        else
            a = graph_map.begin()->first;
    return &a;
}


In case you're wondering, the issue had nothing to do with the absurd pointer scope- rather, it was the invalidation of the iterator when you use erase() with an unordered_set or unordered_map. Which, by the way, is the same cause of the next (two) segmentation faults.

EDIT: Make that 4- turns out I need a different way to return a pointer to the vertex upon creation- as of now, those tend to point to nowhere.

EDIT EDIT: Well, I figured out one issue- I need to update where pointers are pointing to whenever there's an operation that changes a vertex from graph_map to vertex_holder. Otherwise, I get segmentation faults all over the place.

EDIT EDIT EDIT: Marking this as solved while I track down a segfault related to a destructor for vertex.
Last edited on
Topic archived. No new replies allowed.