Valgrind Testing of non Virtual Destructor

By | November 23, 2020

What is the purpose of Virtual Destructor? Sometime this question is asked on job interview. The main purpose of virtual destructor is to keep appropriate clean-up sequence when object is disposed. Deleting a derived class object which is casted to pointer of base class may be result of memory leak if base class destructor is not defined as virtual. Valgrind tool may show such leaks. First you need to install Valgrind.
Let us create small c++ program which contains base and derived class. The destructor of base class is non virtual. In the main function the program instantiates object of derived class and casts the derived class object to the pointer of base class, then delete the object using base class pointer:


#include <stdio.h>
class Base
{
   private:
      char * s;
   public:
      Base(int n)
      {
         s = new char[n];
         printf("Base class. Allocate array of %d characters\n", n);
      }
      ~Base()
      {
         delete[] s;
         printf("Base class. Free character array\n");
      }
};
class Derived : public Base
{
   private:
      char * s;
   public:
      Derived(int n) : Base(n)
      {
         s = new char[n];
         printf("Devived class. Allocate array of %d characters\n", n);
      }
      ~Derived()
      {
         delete[] s;
         printf("Devived class. Free character array\n");
      }
};
int main(int n, char ** s)
{
      Base * base = (Base*)new Derived(100);
      delete base;
}

Program allocates 100 bytes in the base class and another 100 bytes in derived class. Derived and base class destructors should free allocated memory.
Compile and run program:


# ./vdestr
Base class. Allocate array of 100 characters
Devived class. Allocate array of 100 characters
Base class. Free character array

The program output shows that both base and derived classes allocate memory but only base class free it.
Testing with Valgrind:


# valgrind --tool=memcheck --leak-check=full ./vdestr
==11591== Memcheck, a memory error detector
==11591== Copyright (C) 2002-2017, and GNU GPL’d, by Julian Seward et al.
==11591== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==11591== Command: ./vdestr
==11591==
Base class. Allocate array of 100 characters
Devived class. Allocate array of 100 characters
Base class. Free character array
==11591==
==11591== HEAP SUMMARY:
==11591==    in use at exit: 100 bytes in 1 blocks
==11591== total heap usage: 5 allocs, 4 frees, 73,944 bytes allocated
==11591==
==11591== 100 bytes in 1 blocks are definitely lost in loss record 1 of 1
==11591==   at 0x4C3089F: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==11591==   by 0x108A07: Derived::Derived(int) (vdestr.cpp:25)
==11591==   by 0x108915: main (vdestr.cpp:36)
==11591==
==11591== LEAK SUMMARY:
==11591==   definitely lost: 100 bytes in 1 blocks
==11591==   indirectly lost: 0 bytes in 0 blocks
==11591==    possibly lost: 0 bytes in 0 blocks
==11591==   still reachable: 0 bytes in 0 blocks
==11591==       suppressed: 0 bytes in 0 blocks
==11591==
==11591== For counts of detected and suppressed errors, rerun with: -v
==11591== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

Valgrind detects 100 byte memory leak.
To fix this leak we need to declare base class destructor as virtual:


   virtual ~Base()
   {
      delete[] s;
      printf(“Base class. Free character array\n”);
   }

Recompile and execute corrected version:


# ./vdestr
Base class. Allocate array of 100 characters
Devived class. Allocate array of 100 characters
Devived class. Free character array
Base class. Free character array

Now derived and base classes deallocate memory and Valgrind tool also does not detect memory leak anymore:


# valgrind --tool=memcheck --leak-check=full ./vdestr
==11807== Memcheck, a memory error detector
==11807== Copyright (C) 2002-2017, and GNU GPL’d, by Julian Seward et al.
==11807== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==11807== Command: ./vdestr1
==11807==
Base class. Allocate array of 100 characters
Devived class. Allocate array of 100 characters
Devived class. Free character array
Base class. Free character array
==11807==
==11807== HEAP SUMMARY:
==11807==    in use at exit: 0 bytes in 0 blocks
==11807==  total heap usage: 5 allocs, 5 frees, 73,952 bytes allocated
==11807==
==11807== All heap blocks were freed -- no leaks are possible
==11807==
==11807== For counts of detected and suppressed errors, rerun with: -v
==11807== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

Leave a Reply

Your email address will not be published. Required fields are marked *