0

I had a memory leak in my code so I stripped it down to debug it. The culprits are the std::stack data members in the Solitaire::State struct. It's specifically the ones in the nested State struct; if I add a stack data member to the Solitaire class it doesn't leak.

How exactly do I make sure these stacks get deallocated?

#include <iostream>
#include <fstream>
#include <stack>

class SearchState {
public:
protected:
};

class SearchDomain {
public:
    ~SearchDomain();
protected:
    SearchState* init = nullptr;
};

SearchDomain::~SearchDomain() {
    if (init != nullptr)
        delete init;
}

class Solitaire : public SearchDomain {

    enum {
        Npos = 13,
        Nrank = 13,
        Nsuit = 4,
        Ncards = Nrank * Nsuit,
        Ndeck = 24,
        Nfound = 4,
        Ntab = 7,

        pDeck = 0,
        pPile = 1,
        pFound = 2,
        pTab = 6
    };

public:

    struct State : public SearchState {
    public:
        State(std::ifstream& in);
        ~State();
    private:
        int pos = 0;
        std::stack<int> Deck;
        std::stack<int> Pile;
        std::stack<int> Found[Nfound];
        std::stack<int> TabV[Ntab];
        std::stack<int> TabH[Ntab];
    };
    
    Solitaire(std::ifstream& in);
private:
};

Solitaire::Solitaire(std::ifstream& in) {
    init = new State(in);
}

Solitaire::State::State(std::ifstream& in) {

}

Solitaire::State::~State() {

}

int main() {
    while (true) {
        std::ifstream in("instance.txt");
        Solitaire* s = new Solitaire(in);
        in.close();
        delete s;
    }
}
Dugongue
  • 81
  • 1
  • 5

1 Answers1

2

Since Solitaire inherits from SearchDomain, but your SearchDomain destructor deletes a pointer to the base class SearchState, the base class needs to have a virtual destructor.

class SearchState {
friend class SearchDomain;
protected:
    virtual ~SearchState() = default;
};

Without this, Solitaire::States destructor will not get called, and thus its members will not be destroyed either.

The standard does not define a way for destroying the derived class from the base class pointer without a virtual destructor. So technically, deleting the downcast pointer to the derived object without a virtual destructor in the base class is undefined.

More information about when to use virtual destructors can be found here.

Try it online!

jxh
  • 69,070
  • 8
  • 110
  • 193