Search code examples
c++visual-c++destructorrule-of-three

Unusual destructor behaviour when copying over stack variables


I wrote a test to check whether destructors were called before an overwriting assignment on a stack variable, and I can't find any rational explanation for the results...

This is my test (in Visual C++ 2008 Release mode):

#include <iostream>
class C {
public:
 char* ptr;
 C(char p) { ptr = new char[100]; ptr[0] = p;}
 ~C() { std::cout << ptr[0] << ' '; delete [] ptr; }
};

int _tmain(int argc, _TCHAR* argv[])
{
 {
  C s('a');
  s = C('b');
  s = C('c');
  s = C('d');
 }
 std::cin.get();
 return 0;
}

I was expecting to get either "a b c d " if my hypothesis was true, or just "d " if false. Instead I get "b c d x ". The "x " changes depending on how much memory is allocated to ptr indicating that it's reading random heap values.

I believe what is happening (correct me if I'm wrong) is that each constructor call creates a new stack value(lets call them s1, s2, s3, s4), and then the assignments leave s1.ptr overwritten by s4.ptr. s4 is then destroyed immediately after the copy but s1(with a dangling ptr) is destroyed upon leaving the scope, causing a double delete of s4.ptr and no delete of the original s1.ptr.

Is there any way around this unhelpful behavior that doesn't involve using shared_ptrs?

edit: replaced 'delete' with 'delete []'


Solution

  • Rule of Three

    Your application behavior is undefined, since as stated multiple objects will share access to a common pointer and will attempt to read it...

    The rule of three states that each time you define one of:

    • copy constructor
    • assignment operator
    • destructor

    Then you should define the other, since your object has a specific behavior that the default generated methods don't know about.

    EDIT special exception:
    sometimes you only define the destructor because you want it virtual, or because it logs something, not because there is some special handling of your attributes ;)