Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Singleton pattern destructor C++

i have this singleton pattern and it runs ok. But when i execute my program with valgrind to check memory leaks, it seems that the instance is never destroyed.

Where is my mistake?

Header

class Stopwords {   
    private:
        static Stopwords* instance;
        std::map<std::string,short> diccionario;

    private: 
    Stopwords();

    public:
        ~Stopwords();

    public:
    static Stopwords* getInstance();
    std::map<std::string,short> getMap();
};

.cpp

Stopwords* Stopwords::instance = NULL;

Stopwords::Stopwords() {
    diccionario = map<string,short>();

    char nombre_archivo[] = "stopwords/stopwords.txt";
    ifstream archivo;
    archivo.open(nombre_archivo);
    string stopword;
    while(getline(archivo,stopword,',')) {
    diccionario[stopword] = 1;
    }
    archivo.close();
}

Stopwords::~Stopwords() {
    delete instance;
}


Stopwords* Stopwords::getInstance() {

    if (instance == NULL) {
       instance = new Stopwords ();
    }
    return instance;
}

map<string,short> Stopwords::getMap(){
    return diccionario;
}

It's not relevant but in the initialization, i read a bunch of words from a file and i save them in a map instance.

Thanks

like image 385
user3013172 Avatar asked Nov 20 '13 14:11

user3013172


People also ask

Can a singleton class have destructor?

No, and in general objects in C++ are not given private destructors. Keep in mind that Singleton means that there is only one instance, and so it is construction, not destruction, that needs to be controlled / prevented.

Can you destroy a singleton object?

Longer answer: You cannot destroy a singleton, except you use a special Classloader. If you need to destroy it, you shouldn't use a singleton at all.

How do I delete an object in singleton?

And deletion of singleton class object would be allow only when the count is zero. To design C++ delete singleton instance, first, we need to make the singleton class destructor private, so, it can not be accessed from outside of the class. Hence, user cannot delete the singleton instance using the keyword “delete”.

Can singleton cause memory leak?

Second, developers may inadvertently reference objects from Singletons. These referenced objects would normally be garbage collected, but because Singletons stay in memory for as long as the program is running, they will keep these "other" objects in memory as well, causing a memory leak.


3 Answers

The problem is that you never call the destructor or delete on the instance pointer by hand, i.e. from outside the class. So the delete inside the destructor will never get executed, meaning the destructor will never get executed, meaning the delete will never get executed, meaning... You see what you did there? Your destructor is indirectly calling itself which will not go well. And you never call it from the outside, so it never gets called at all - luckily.

You should change your singleton implementation, maybe a Meyers singleton (look it up), or even better not use a singleton at all. In cases like this one, where they are data sources, there are just too much weaknesses of the pattern to deal with.

like image 193
Arne Mertz Avatar answered Nov 15 '22 21:11

Arne Mertz


Stopwords::~Stopwords() {
    delete instance;
}

This is the destructor for instances of the class. You probably intended this function to be called when the program ends, as though it were a kind of 'static' destructor, but that's not what this is.

So your destructor for instances of Stopwords initiates destruction of Stopwords instances; You've got an infinite loop here, which you never enter. If you do get into this loop then the program will probably just crash.

There's a simpler way to do singletons: Instead of keeping the instances as a static class member that you allocate manually, simply keep it as a static function variable. C++ will manage creating and destroying it for you.

class Stopwords {   
public:
    static Stopwords &getInstance() {
        static Stopwords instance;
        return instance;
    }

    ~Stopwords();
    std::map<std::string,short> getMap();

private:
    Stopwords();
    std::map<std::string,short> diccionario;
};

Also, you should mark member functions that don't need to modify the class as const:

std::map<std::string,short> getMap() const;
like image 39
bames53 Avatar answered Nov 15 '22 20:11

bames53


  1. You allocate memory for instance with new. So the instance will be alive until delete is called.
  2. Destructor is called in the case an instance of a class going to be killed.
  3. Nothing kills (using delete) your instance, but destructor itself.

So the conclusion is that your instance is never killed.

Usually, when you use singleton you don't care to kill it before the program finishes. Why do you need this?

If you don't you better use static keyword to make explicit the fact that it is alive until the program finishes.

static Singleton& getInstance()
{
     static Singleton s;
     return s;
}
like image 28
klm123 Avatar answered Nov 15 '22 20:11

klm123