0

I have a structure defined that contains a std::list. In my code, I try to iterate through this list, but I get some odd results.

struct my_struct_t {
    std::list<int> my_list;
    //More fields
};

This is my structure as defined in my header file.

And some sample code in a file that includes this header would be:

    std::list<int>::iterator my_iterator;

    struct my_struct_t* test_struct = (struct my_struct_t*) malloc(sizeof(struct my_struct_t));
    my_iterator = test_struct->my_list.begin();
    printf("Beginning of list address: %p\n", my_iterator);

    my_iterator = test_struct->my_list.end();
    printf("End of the list address: %p\n", my_iterator);
    printf("Address of the list: %p\n", &(test_struct->my_list));

This code compiles and runs fine, but the output would be something like:

Beginning of list address: (nil)
End of the list address: 0x86f010
Address of the list: 0x86f010

The last two lines make perfect sense to me, since the list should be empty. But how/why am I getting a null pointer for the beginning? How can I fix this?

alk
  • 69,737
  • 10
  • 105
  • 255
Arcaten
  • 33
  • 1
  • 5
  • 1
    Step 1: Read a good C++ primer, pick one among [those](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list). Step 2: realize that despite the many similarities, C++ and C are very different languages and are only really alike in their flaws. – Matthieu M. Feb 20 '13 at 07:23

2 Answers2

8

You can't malloc a list and then use it without initialization. This is an invalid operation.

It has not been initialized with a proper new call. That this works at all without blowing a segfault is amazing.

You will need to create your my_struct_t object using a C++ style initialization or it won't work.

Have you tried something more C++ like:

struct my_struct_t* test_struct = new my_struct_t;

Later on instead of a free call you would delete of course.

tadman
  • 208,517
  • 23
  • 234
  • 262
  • 1
    You don't need a new call.. but at least a call to the constructor – Kek Feb 20 '13 at 07:20
  • 1
    Calling a constructor on a `malloc`'d object seems like a dangerous road to go down. If the `list` has a destructor you'd have to call that manually before issuing a `free`. – tadman Feb 20 '13 at 07:22
  • Yes. I meant : you could create your sctruct on the stack... or call a new for the struct, not the list – Kek Feb 20 '13 at 07:25
  • Nothing there is invalid. The code is just not doing what he expects. He could still use placement new to correctly initialize the object and code like this has valid use-cases. – pmr Feb 20 '13 at 07:28
  • I think that approach would get [the book](http://www.aristeia.com/books.html) thrown at you. Considering how the `new` call is significantly easier to perform, there's really no reason to do a `malloc` here. – tadman Feb 20 '13 at 07:31
  • @tadman Sure, this is not really what he wants to do. But your answer is giving the impression of something not being permissible, which is false. – pmr Feb 20 '13 at 07:34
  • I've clarified my answer slightly to address this. – tadman Feb 20 '13 at 07:46
1

malloc will only allocate the necessary memory for an object, but will not initialize that object. Initialization of an object in C++ is performed by its constructor. C++ provides the operator new to allocate memory and initialize an object at the same time. So what you should have done is:

my_struct_t* x = new my_struct_t();

If you really intended to use malloc here, you can still properly initialize an object on in correctly aligned raw-memory by using placement new. Keep in mind that you will then have to call the destructor explicitly and deallocate the memory explicitly as well. But I seriously doubt this was your intention.

pmr
  • 58,701
  • 10
  • 113
  • 156