1

Given the code :

class Sample
{
 public:
      int *ptr;
      Sample(int i)
      {
      ptr = new int(i);
      }
      ~Sample()
      {
      delete ptr;
      }
      void PrintVal()
      {
      cout << "The value is " << *ptr;
      }
 };
 void SomeFunc(Sample x)
 {
     cout << "Say i am in someFunc " << endl;
 }
 int main()
 {
     Sample s1= 10;
     SomeFunc(s1);
     s1.PrintVal();
 }

The output is :

Say i am in someFunc
Null pointer assignment(Run-time error)

I'm not able to understand why the second line of output comes. The second line of the output. I think that the compiler supplies a copy constructor when it is not explicitly specified. So, in the function SomeFunc(Sample x), the local object to SomeFunc() which is X of Sample type should be created and destroyed and the Sample type object (s1) in main() should remain intact and should be freed only after main exits. Please answer why the above behaviour is happening?

Peter Wood
  • 23,859
  • 5
  • 60
  • 99
Abhay
  • 129
  • 2
  • 11

1 Answers1

6

Why the above behaviour is happening??

Short Answer:
Because You are not following the Rule of Three.

Long Answer:
Your class has a pointer member ptr with dynamic memory allocation in constructor and deallocation in destructor while your code creates temporary copies of the object while passing to the function SomeFunc() by calling copy constructor, implicitly generated by the compiler, which creates a shallow copy of the pointer member. Once the temporary is destroyed at the end of function call the memory is deallocated in destructor and you are left with a dangling pointer.This invalid pointer is dereferenced further when you call the function PrintVal() resulting in a Undefined Behavior, which manifests in the form of a segmentation fault.

How to avoid this problem?

Short Answer:
Follow the Rule of Three.

Long Answer:
You should provide a copy constructor which creates a deep copy of the pointer member ptr. This ensures that the pointer member of the object created in member remains valid through out the lifetime of the program.

EDIT:
Actually, the problem might even occur even before the function gets called, specifically when you call:

Sample s1= 10;

This calls the conversion constructor,

 Sample(int i)

to create a temporary Sample object which is then used for constructing s1 object by calling the implicit copy constructor, If this is the case the temporary object created will be destroyed after creation of s1 does leaving the pointer member ptr in a dangling state.

However, most of the compilers will apply optimizations through copy elision using Return Value Optimization(RVO) thus eliminating the need of calling the copy constructor & hence this might not be a problem.

In either case solution to the problem remains the same.

Community
  • 1
  • 1
Alok Save
  • 202,538
  • 53
  • 430
  • 533
  • +1 for the edit mentioning the case of conversion constructor, though that is the not the cause here due to RVO – Sanish Mar 16 '12 at 06:46
  • @Als: I created my Stack Exchange account today itself and I'm amazed by the quality of answers and the swiftness of response. :) – Abhay Mar 16 '12 at 13:27
  • @Abhay: Welcome on-board, Happy Learning, See you around :) – Alok Save Mar 16 '12 at 14:01