I have an abstract class. I'm creating a large array in the base class, which appears to never be deleted because no destructor is called. My questions (obviously) are...

  • Why isn't a destructor called?
  • How do I fix it?

    #include <iostream>
    using namespace std;
    
    class A
    {
    protected:
        int* b;
    public:
        A()
        {
            cout << "ANull\n";
            b = new int[1000000];
        }
        ~A()
        {
            cout << "ADest\n";
            delete b;
        }
        virtual void foo() = 0;
    };
    
    
    class B: public A
    {
    private:
        static int c;
    public:
        B()
        {
            c++;
            b[5] = c * 2;
            cout << "BNull\n";
        }
        ~B()
        {
            cout << "BDest\n";
        }
        void foo()
        {
            cout << "B(b[5],c) = (" << b[5] << "," << c << ")\n";
        }
    };
    int B::c = 0;
    
    int main()
    {
        for(int i = 0; i < 1000000; i++)
        {
            A* obj = new B();
            obj->foo();
        }
        cin.get();
        return 0;
    }
    

Output

ANull
BNull
B(b[5],c) = (2,1)
ANull
BNull
B(b[5],c) = (4,2)
ANull
BNull
B(b[5],c) = (6,3)
ANull
BNull
B(b[5],c) = (8,4)
ANull
BNull

Etcetera. Neither "ADest" nor "BDest" is ever displayed. The behavior is that the loop whizzes by till c gets to be about 300, then things slow down, which seems like what you'd expect for a big memory leak, which appears to be what's happening since the destructor is not being called.

You have a massive memory-leaking loop. No surprise that it crashes your system. In the loop inside main, you allocate B objects and never delete them. This is a more correct loop:

for(int i = 0; i < 1000000; i++)
{
    A* obj = new B();
    obj->foo();
    delete obj;  // this line is very important!
}

Also, when you need a temporary object only for the span of an iteration, you should just use a local variable, that is the favored mechanism in C++:

for(int i = 0; i < 1000000; i++)
{
    B obj;
    obj.foo();
}

Finally, DO NOT forget to make your base-class destructor virtual!!! This is very important to make sure that the most derived class destructor is called when you delete the object via a base-class pointer.

virtual ~A()
{
    cout << "ADest\n";
    delete b;
}

Excellent. Things work much better now! Thanks.

I know this is solved, but a detail which should not go unnoticed, namely

// Allocate ...
b = new int[1000000];

// ... and delete
delete [] b;

//// instead of
// delete b;
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.