Why do I get segmentation fault when I try to access member data of outer class from nested class?

318 Views Asked by At

I have a class Outer with a nested class Inner. Inner has a method 'print' which tries to access a data member of class Outer. The code compiles fine but I get a segmentation fault error when I try to run the programme.

#include <iostream>

class Outer{
public:
  Outer();
  ~Outer();

  class Inner{
  public:
    Inner(Outer *parent){}
    void print(){std::cout<< parent-> data <<std::endl;}
  private:
    Outer *parent;
  };
  Inner *obj;

private:
  int data;
};

Outer::Outer(): data(99), obj(new Inner(this)){}
Outer::~Outer(){delete obj;}

int main(){
  Outer outer;
  outer.obj->print();
  return 0;
}

I'm not sure what is the issue as I have already passed the 'this' pointer to the inner object.

The code is compiled with g++4.8.2 using the c++11 flag.

3

There are 3 best solutions below

0
Christian Hackl On BEST ANSWER

You must turn on compiler warnings and pay attention to them. In this case, the compiler is able to pinpoint the exact error in:

 Inner(Outer *parent){}
warning: unused parameter 'parent' [-Wunused-parameter] In constructor 'Outer::Outer()':

(The exact warning message may differ, but all major compilers are able to detect this if you don't prevent them from doing so by using some low default warning level.)

As you leave the parent member variable in an uninitialised status, the following line invokes undefined behaviour because you try to read from the variable:

 void print(){std::cout<< parent-> data <<std::endl;}

You must initialise the member variable:

Inner(Outer *parent) : parent(parent) {}

That's not the only problem, though. There's also this:

18:7: warning: 'Outer::data' will be initialized after [-Wreorder]
15:10: warning: 'Outer::Inner* Outer::obj' [-Wreorder]
21:1: warning: when initialized here [-Wreorder]

You can fix it by simply changing the order as follows:

Outer::Outer(): obj(new Inner(this)), data(99) {}
0
ChronoTrigger On

You are not storing the pointer to the Outer class in the Inner constructor:

Inner(Outer *parent) : parent(parent) {}

Also, if you use C++11, this may be a good case to use smart pointers.

0
NathanOliver On

You are not doing anything with parent in

Inner(Outer *parent){}

You need to Inners parent member in the constructor

Inner(Outer *parent_) : parent(parent_){}