stl set insert problem

Hello all,
thanks in advance for the help.

I'm trying to get back into C++ programming after a few years mainly programming java. I thought I'd try to implement a simple graph to get me started.

The code:
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
/*
 * Main.cpp
 *
 *  Created on: 19/10/2012
 */
#include <iostream>
#include <set>
#include <map>
#include <stdio.h>
#include <stdlib.h>
#include <vector>

using namespace std;


class Node
{
private:
	int id;
	string name;
	set <Node*> adjacents;
	bool visited;
//	static int b ;
//	static set <int> allids;
public:
	Node(string str)
	{
		id = -1;
		visited = false;
		name = str;
		adjacents = set <Node*>();
//		b = 4;
	}

	void addAdjacent(Node * n)
	{
		adjacents.insert(n);
	}

	string getName()
	{
		return name;
	}

	int getId()
	{
		return id;
	}

	void setId(int _id)
	{
//		if(allids.find(_id) != allids.end())
//		{
//			cout << "Error, already have id " + _id << endl;
//			exit(-1);
//		}
		id = _id;
	}

	set <Node*> getAdjacents()
	{
		return adjacents;
	}

	void print(string indent)
	{
		cout << indent << id << ": ";
		set<Node*>::iterator it = adjacents.begin();
		while(it != adjacents.end())
		{
			cout << "(" << (*it)->getId() << ", " << (*it)->getName() << ")" << ", ";
			it++;
		}
		cout << endl;
	}

	void setVisited(bool v)
	{
		visited = v;
	}

	bool isVisited()
	{
		return visited;
	}
};
//static int b = 0;
//const set <int> Node::allids;

//const set <int> Node::allids;

class Graph
{
public:
	Graph()
	{
		//root = new Node("root");
		nodes = new map <int, Node*>();
		allNodes = set <Node*>();
		idAt = 0;
	}

	void initGraph(vector <pair <int, int> > _nodes)
	{
		cout << "ig" << 1 << endl;
		bool first = false;
		//Node * firstNode;

		for(int i = 0; i < _nodes.size(); i++)
		{
			cout << "ig" << 2 << endl;
			pair <int, int> p = _nodes[i];
			if((*nodes)[p.first] == NULL)
			{
				cout << "Creating" << endl;
				createNode("Node", p.first);
				cout << "Created" << endl;
			}
			else
			{
				cout << "Not creating, " << (*nodes)[p.first] << " != " << NULL << endl;
			}
			if((*nodes)[p.second] == NULL)
			{
				createNode("Node", p.second);
			}
			if((*nodes)[p.first] == NULL || (*nodes)[p.second] == NULL)
			{
				cout << "Error, node creation unsuccessful" << endl;
				exit(-1);
			}
			cout << "Trying to link" << endl;
			createLink((*nodes)[p.first], (*nodes)[p.second]);
			cout << "Linked" << endl;
			if(!first)
			{
				first = true;
//				createLink(root, nodes[p.first]);
				root = (*nodes)[p.first];
			}
			cout << "ig" << 3 << endl;
		}
		cout << "ig" << 4 << endl;
	}

	void createLink(Node * n1, Node * n2)
	{
		n1->addAdjacent(n2);
	}

	Node * createNode(string name, int id)
	{
		cout << "Name is " << name << endl;
		Node * n = new Node(name);
		cout << "Now Name is " << n->getName() << endl;
		n->setId(id);
		if((*nodes)[id] != NULL)
		{
			cout << "Error, nodes[" << id << "] not nodes.end()";
			exit(-1);
		}
		//nodes->insert(pair <int, Node*> (id, n));
		//nodes.insert(make_pair(id, n));
		pair <map <int, Node*>::iterator, bool> result = nodes->insert(make_pair(id, n));
		cout << "Status = " << result.second << endl;
		cout << "Iterator = " << result.first->first << flush;
		cout << ", " << result.first->second->getId() << endl;
		//(*nodes)[id] = n;
		cout << "Max size " << nodes->max_size() << endl;
		//make_pair(id, n);
		if((*nodes)[id] == NULL)
		{
			cout << "Should NOT be null" << endl;
			cout << "Size is " << nodes->size() << endl;
			map <int, Node*>::iterator it = nodes->begin();
			cout << "Looking for " + id << endl;
			cout << "Nodes present:" << endl;
			while(it != nodes->end())
			{
				cout << (*it).first << ", " << (*it).second->getId() << endl;
				it++;
			}
			exit(-1);
		}
		//nodes[id] = n;
		allNodes.insert(n);
		return n;
	}

	/*
	void addNode(Node * n)
	{
		int id = idAt++;
		n->setId(id);
		nodes->insert(pair <const int, Node*> (id, n));
		allNodes.insert(n);
	}*/

	Node * getRoot()
	{
		return root;
	}

	void printGraphHelper(Node * n, string indent)
	{
	//	cout << "Visiting " << n->getId() << endl;
		n->print(indent);
		n->setVisited(true);
		indent += "  ";
		set <Node*> adjacents = n->getAdjacents();
		set<Node*>::iterator it = adjacents.begin();
		while(it != adjacents.end())
		{
			//cout << "At " << !(*it)
			if(!(*it)->isVisited())
			{
				printGraphHelper((*it), indent);
			}
			it++;
		}
	}

	void printGraph()
	{
		clearAllFlags();
		printGraphHelper(root, "");
	}

	void clearAllFlags()
	{
		set<Node*>::iterator it = allNodes.begin();
		while(it != allNodes.end())
		{
			(*it)->setVisited(false);
			it++;
		}
	}

private:
	Node * root;
	set <Node*> allNodes;
	map <int, Node*> *nodes;
	int idAt;// = 0;
};

int main ()
{
	Graph * g = new Graph();
	vector <pair <int, int> > v = vector <pair <int, int> >();
	v.push_back(pair <int, int> (0,1));
	v.push_back(pair <int, int> (1,2));
	v.push_back(pair <int, int> (1,3));
	v.push_back(pair <int, int> (1,4));
	v.push_back(pair <int, int> (3,4));
	v.push_back(pair <int, int> (4,5));
	v.push_back(pair <int, int> (2,5));
	v.push_back(pair <int, int> (5,1));
	g->initGraph(v);
	cout << "GraphInit" << endl;
	g->printGraph();
	return 0;
}


The problem is in the createNode() function in the graph class when I try to insert the node into the nodes map that keeps track of all my nodes by id.
If I use this way of inserting into the map (currently commented out):
(*nodes)[id] = n;
everything works fine.

However, if I use this way:
pair <map <int, Node*>::iterator, bool> result = nodes->insert(make_pair(id, n));
which as far as I understand should be equivalent, then the if conditional if((*nodes)[id] == NULL) fires and the program crashes (segmentation fault) when I try to use the iterator to print out all the values in the nodes map.
When I use the gdb debugger, if if remove the cout lines right after the insert then it shows me the application crashes when trying to call the getId() method in the second line of this loop:
1
2
3
4
5
while(it != nodes->end())
{
        cout << (*it).first << ", " << (*it).second->getId() << endl;
	it++;
}

I also notice that the return value from the insert call is 'false' for result.second, indicating that the value was not successfully inserted.

I am using Eclipse and the mingw g++ compiler.

I'm probably doing something really silly so apologies in advance but I just can't seem to figure it out.

Thanks again!
Last edited on
If you've used the [] operator as nodes[id] at any point before you do the insert, I'm fairly certain that creates an uninitialized value at 'id'. So any insert call afterward would fail as there is already a value where you are trying to insert.
Hey Zhuge,
that's it!

I replaced the nodes[id] == NULL with nodes.find(id) == nodes.end() and now it works like a charm.

Thanks, it was driving me nuts.
Glad I could help.
Topic archived. No new replies allowed.