Question on inheritance, virtual destructors, and the heap

My question is if you have a pointer in a class that is pointing
to heap memory that is automatically deleted once the class's destructor
is called, like below, will making the destructor virtual and/or
creating subclasses off the parent class cause the memory pointed
to by ptr not to be returned correctly?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  SomeClass* f()
{
	SomeClass* ptr = new SomeClass;
	return ptr;
}
class Parent 
{
public:
Parent()
{
	ptr = f();
}

virtual ~Parent()
{
	if(ptr != NULL)
	{
		delete ptr;
	}
}
protected:
	SomeClass* ptr = NULL;
};
Destructors always call the destructors of their parent classes.
Hi AxDragonxg. This is a great time for you to write some tests.

The first question is to wonder if the destructor gets called at all:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>

struct Base  // using structs because they have public access by default
{
  virtual ~Base( void )
  {
    std::cout << "Base Destructor\n";
  }
};

struct Child : public Base
{
  ~Child( void )
  {
    std::cout << "Child Destructor\n";
  }
};

int main( void )
{
  Base* ptr = new Child();
  delete ptr;

  return 0;
}


Running this program, the output is:
1
2
Child Destructor
Base Destructor


So yes, we are calling both destructors. Let us add the dynamic pointer to the base:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <iostream>

struct Data
{
  ~Data( void )
  {
    std::cout << "Data destructor\n";
  }
};

struct Base
{
  Base( void )
  {
    data = new Data();
  }

  virtual ~Base( void )
  {
    delete data;
    std::cout << "Base Destructor\n";
  }

  Data* data;
};

struct Child : public Base
{
  ~Child( void )
  {
    std::cout << "Child Destructor\n";
  }
};

int main( void )
{
  Base* ptr = new Child();
  delete ptr;

  return 0;
}


Which outputs:
1
2
3
Child Destructor
Data Destructor
Base Destructor


If we aren't happy yet, we can run valgrind:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ g++ -g main.cpp -o prog
$ valgrind --leak-check=yes prog
==3837== Memcheck, a memory error detector
==3837== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==3837== Using Valgrind-3.9.0 and LibVEX; rerun with -h for copyright info
==3837== Command: prog
==3837== 
Child Destructor
Data destructor
Base Destructor
==3837== 
==3837== HEAP SUMMARY:
==3837==     in use at exit: 0 bytes in 0 blocks
==3837==   total heap usage: 2 allocs, 2 frees, 17 bytes allocated
==3837== 
==3837== All heap blocks were freed -- no leaks are possible
==3837== 
==3837== For counts of detected and suppressed errors, rerun with: -v
==3837== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2) 


So yes, it is freed.

The thing to worry about is the child class. If the base class does not have a virtual destructor, then the child's destructor does not get called:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>

struct Base
{
  ~Base( void )
  {
    std::cout << "Base Destructor\n";
  }
};

struct Child : public Base
{
  ~Child( void )
  {
    std::cout << "Child Destructor\n";
  }
};

int main( void )
{
  Base* ptr = new Child();
  delete ptr;

  return 0;
}


Output:
Base Destructor
Thanks for the quick reply. I was unsure how a virtual destructor would act compared to a regular virtual member function so thanks for clearing that up. Also thanks for suggesting valgrind for when I need to debug memory leaks in the future.
Topic archived. No new replies allowed.