STL List to hold structure pointers

c++, list, pointers, segmentation-fault, stl

Solution

There are several things wrong here.

First off, you aren't initializing the iterator, like other's have said:

list<vertex*>::iterator it = r_list->begin();

Do this and your code will be fine. But your code is done in a bad manner.

Why are you allocating the list from the heap? Look at your code: you have a memory leak. You aren't calling `delete r_list` anywhere. This is why you should use smart pointers (`std::unique_ptr`, `std::shared_ptr` if you have C++11, boost equivalents otherwise : `boost::scoped_ptr` and `boost::shared_ptr`)

But better yet, just do it on the stack:

//create a list to hold the vertices
list<vertex*> r_list;

list<vertex*>::iterator it = r_list->begin();

r_list.insert(it, pr);

In addition, using the iterator to insert is going about things the long way. Just use push front() or push back():

//create a list to hold the vertices
list<vertex*> r_list;

r_list.push_back(pr);

Another thing: if your list outlives the vertex you've constructed, it will be pointing to something invalid.

For example:

// global
list<vertex*> r_list;

void some_function(void)
{
    //create the vertices
    vertex r = {WHITE, NULL, NULL};

    //create pointer to the vertex structures
    vertex *pr = &r;

    r_list.push_back(pr);
} // right here, vertex r stops existing: the list now contains an
  // invalid pointer.

One solution is to store pointers to heap-allocated vertices:

// global
list<vertex*> r_list;

void some_function(void)
{
    //create the vertices
    vertex *r = new vertex;
    r->color = WHITE;
    r->distance = 0;
    r->parent = 0;

    r_list.push_back(r);
}

Now even after the function the list is pointing to a valid heap-allocated vertex. This now has the problem that when you're done using the list, you need to go through the lsit and call `delete` on each element. This problem is assisted by using the Boost Pointer Container Library.

The best way, though, is to just store vertices themselves (rather than pointers to them):

//create a list to hold the vertices
list<vertex> r_list;

//create the vertices
vertex r = {WHITE, NULL, NULL};

r_list.push_back(r);

If you give vertex a constructor, you can even just construct them in-place:

struct vertex
{
    int color;
    int distance;
    char parent;

    vertex(int _color, int _distance, char _parent) :
    color(_color),
    distance(_distance),
    parent(_parent)
    {
    }
};

//create a list to hold the vertices
list<vertex> r_list;

r_list.push_back(vertex(WHITE, NULL, NULL));

(these are now outside your problem)

Firstly, NULL is generally only used when dealing with pointers. Since `distance` and `parent` are not pointers, use `0` to initialize them, rather than `NULL`:

//create the vertices
vertex r = {WHITE, 0, 0};

Secondly, use `constants` rather than `#define`:

#define NUM_VERTICES 8 // <- bad
const int NumberVertices = 8; // <- good

Lastly, give your enum a name, or place it in a namespace:

enum Color { WHITE, GRAY, BLACK };

Hope these help!

Problem

I have a structure called vertex and I created some pointers to them. What I want to do is add those pointers to a list. My code below, when it tries to insert the pointer into the list, creates a segmentation fault. Can someone please explain what is going on? ``` #include <iostream> #include <list> #define NUM_VERTICES 8 using namespace std; enum { WHITE, GRAY, BLACK }; struct vertex { int color; int distance; char parent; }; int main() { //create the vertices vertex r = {WHITE, NULL, NULL}; //create pointer to the vertex structures vertex *pr = &r; //create a list to hold the vertices list<vertex*> *r_list = new list<vertex*>; list<vertex*>::iterator it; r_list->insert(it, pr); } ```

Original source