Search code examples
c++segmentation-faultstdlist

Why does this cause a segfault in C++?


When I try to add an Object pointer to a std::list pointer I get a segfault. Why?

object.h

#ifndef DELETEME_H
#define DELETEME_H
class Object
{
public:
  Object(): yes(0) {};
  int yes;
};
#endif

object.cpp

#include <list>
#include "deleteme.h"

int main()
{
  std::list<Object*> *pList;
  Object *pObject;
  pObject = new Object();
  pList->push_front(pObject);
}

Solution

  • It causes a segfault because pList is not initialized.

      std::list<Object*> *pList;    // You declared it but you have not said what
                                    // value lives here.
    

    So when you try and use it:

      pList->push_front(pObject);   // This is undefined behavior.
    

    If you turn your compiler warning on(up) the compiler will warn you this is a problem. You should really tell your compiler to treat all warnings as errors.

    How do you solve it.

    You should create a list.

    std::list<Object*> *pList  = new std::list<Object*>;
    

    But creating it as a pointer is a bad idea (no a very bad idea). You have just opened up a hole can of worms that you don't want to handle. You should never (read hardly ever (or just never)) dynamically create memory. It leads to all sorts of problems with exceptions and leaks. Until you understand ownership semantics stick to objects.

    std::list<Object> pList;
    pList.push_back(Object());
    

    In the comments you are worried about returning it from a function.

    std::list<Object>  getList()
    {
       std::list<Object>   result;
       result.push_back(Object());
       result.push_back(Object());
    
       return result;
    }
    int main()
    {
         // Technically this copies the list out of the function
         // when the return is called (so your object and the list)
         // must be copyable.
         std::list<Object>   data = getList();
    
         // But in reality it will not be copied.
         // Because the copiler will invoke NRVO and build it in place
         // at the destination. If you put print statements in your objects
         // constructor/destructor etc.. you can try and spot the copies.
    
         // Turn on optimizations and any copies that did exist will be
         // removed.
    }