Joe Fanelli
Joe Fanelli

Reputation: 41

Preventing memory leaks in polymorphic classes

In the following exercise I have created a polymorphic relationship between a base class and several derived classes:

#include <iostream>
using namespace std;

class Panthera
{
public:
    virtual void roar() = 0;
    virtual ~Panthera() {}
};

class Lion : public Panthera
{
public:
    void roar() { cout << "roaring like a lion... " << endl; }
};

class Tiger : public Panthera
{
public:
    void roar() { cout << "roaring like a tiger..." << endl; }
};

class Jaguar : public Panthera
{
public:
    void roar() { cout << "roaring like a jaguar... " << endl; }
};

class Leopard : public Panthera
{
public:
    void roar() { cout << "roaring like a leopard... " << endl; }
};

void speak(Panthera *object)
{
    object->roar();

    delete object; // this is meant to prevent memory leak

    cout << "deleting pointer... " << endl;
}

int main()
{

    Lion lion;
    Tiger tiger;
    Jaguar jaguar;
    Leopard leopard;

    speak(&lion);
    speak(&tiger);
    speak(&jaguar);
    speak(&leopard);

    cout << "program ending... " << endl;

}

I have set the base class destructor to virtual and deleted the pointer in the function "speak" to prevent memory leaks, and while the code does compile and run without any warnings or errors, I get the following results from a memory leak detector:

Error #1: INVALID HEAP ARGUMENT to free 0x0028ff2c
# 0 replace_free               [d:\drmemory_package\com...
# 1 Lion::~Lion                [../src/bigCats.cpp:11]
# 2 speak                      [../src/bigCats.cpp:39]
# 3 main                       [../src/bigCats.cpp:52]
Note: @0:00:01.466 in thread 7936

Error #2: INVALID HEAP ARGUMENT to free 0x0028ff28
# 0 replace_free                [d:\drmemory_package\com...
# 1 Tiger::~Tiger               [../src/bigCats.cpp:17]
# 2 speak                       [../src/bigCats.cpp:39]
# 3 main                        [../src/bigCats.cpp:53]
Note: @0:00:01.482 in thread 7936

Error #3: INVALID HEAP ARGUMENT to free 0x0028ff24
# 0 replace_free                  [d:\drmemory_package\com...
# 1 Jaguar::~Jaguar               [../src/bigCats.cpp:23]
# 2 speak                         [../src/bigCats.cpp:39]
# 3 main                          [../src/bigCats.cpp:54]
Note: @0:00:01.497 in thread 7936

Error #4: INVALID HEAP ARGUMENT to free 0x0028ff20
# 0 replace_free                    [d:\drmemory_package\com...
# 1 Leopard::~Leopard               [../src/bigCats.cpp:29]
# 2 speak                           [../src/bigCats.cpp:39]
# 3 main                            [../src/bigCats.cpp:55]
Note: @0:00:01.529 in thread 7936

I also noted that the program has crashed occasionally at random intervals, although it does seem to work most of the time. Curiously when I get rid of the "delete object" command in the "speak" function, these errors from the memory leak detector completely disappear.

Can someone please explain to me what is going on here? My textbook understanding tells me that I need to delete the pointer to the base class to prevent memory errors and avoid unpredictable program behavior, but I seem to be experiencing the complete opposite.

Upvotes: 1

Views: 338

Answers (2)

Joseph D.
Joseph D.

Reputation: 12174

From class.dtor#12

A destructor is also invoked implicitly through use of a delete-expression for a constructed object allocated by a new-expression;

Thus, only use delete operator when you allocate objects using new operator.

Lifetime of an object - The object not allocated by new will be destructed automatically as soon as it goes out of scope (which in your case, when it goes out of main's block scope).

Upvotes: 0

Yakk - Adam Nevraumont
Yakk - Adam Nevraumont

Reputation: 275820

In C++ you must carefully manage all objects lifetime.

delete x is only valid on a pointer to an objeft created by new.

You created objects in automatic storage. There is no need to delete to prevent memory leaks, and doing so is undefined behaviour.

Avoid using raw pointers that "own" resources; use unique_ptr instead when you must heap allocate. Avoid heap allocation; learn the rule of 5, and only heap allocate when required.

Upvotes: 2

Related Questions