Visual Leak Detector



  • Hallo Zusammen,

    Ich habe es vorkurzen den Visual Leak Detector in Visual Studio 15 C++ eingerichtet.
    Es hat mich sehr viel geholfen mehrere Leaks zu detektieren und zu löschen.

    Bei eine der Application verwende ich folgende Code "Singelton":

    Header:

    class Constants : public QObject
    {
    	Q_OBJECT
    
    private:
    	Constants();
    	~Constants();
    
    public:
    	/**
    	* The constants are available as a singleton.
    	*/
    	static Constants* instance()
    	{
    		static QMutex mutex;
    
    		if (_instance == NULL)
    		{
    			mutex.lock();
    			if (_instance == NULL)
    			{
    				_instance = new Constants();
    			}
    			mutex.unlock();
    		}
    		return _instance;
    	}
    	.....
    	private:
    	static Constants* _instance;
    };
    

    cpp
    Constants* Constants::_instance = NULL;
    Bei der main habe ich einfach der

    #include<vld.h>
    

    eingebunden und dann die Application gestartet.
    Es wurde aber bei diesem Codeabschnitt:

    _instance = new Constants();
    

    einen Leak detektiert.
    Wie kann ich denn den Leak umgehen?
    Ist das überhaupt einen Leak?



  • Saheb schrieb:

    Wie kann ich denn den Leak umgehen?

    Den Speicher freigeben?

    Saheb schrieb:

    Ist das überhaupt einen Leak?

    Natürlich. Je nach dem, was dein Destruktor so macht, ist es jedoch belanglos.

    Du kannst die Meldung also entweder ignorieren oder einen Smartpointer verwenden.



  • manni66 schrieb:

    Saheb schrieb:

    Wie kann ich denn den Leak umgehen?

    Den Speicher freigeben?

    Saheb schrieb:

    Ist das überhaupt einen Leak?

    Natürlich. Je nach dem, was dein Destruktor so macht, ist es jedoch belanglos.

    Der Destruktur ist so implementiert:

    Constants::~Constants()
    {
    	delete Constants::_instance;
    }
    

    manni66 schrieb:

    ist es jedoch belanglos.

    Warum ist es belanglos? und wann ist einen Leak gefährlich?

    Danke



  • Constants::~Constants()
    {
        delete Constants::_instance;
    }
    

    und wird er denn auch aufgerufen? zu sehen im Debugger oder mit printf...



  • Ja, man kann das Leak vermeiden und sich ab C++11 auch den Mutex sparen, da hier garantiert ist, dass die Initialisierung
    lokaler statischer Variablen sicher ist, auch wenn mehrere Threads die Funktion konkurrierend erstmalig aufrufen.

    (Implizit erwartet das dein Code bereits, da ansonsten eigentlich auch die Initialisierung des Mutex in instance()
    selbst wiederum durch einen Mutex geschützt werden müsste ;))

    Ich würde das z.B. so umsetzen:

    static const Constants& instance()
    {
        static Constants instance{};
        return instance;
    }
    

    oder

    static const Constants* instance()
    {
        static Constants instance{};
        return &instance;
    }
    

    wenn der weitere Code bereits überall einen Pointer erwartet.

    Unter bestimmten Umständen kann man auch ein (kontrolliertes) Leak einfach akzeptieren, z.B. wenn es andere statische Instanzen
    von Klassen gibt, die in ihrem Destruktor noch auf die Constants -Instanz zugreifen müssen. Da es in einem solchen Fall schwierig sein kann,
    die Reihenfolge der Destruktor-Aufrufe so zu gestalten, dass sie nicht auf eine eventuell bereits zerstörte Constants -Instanz zugreifen,
    überlässt man schonmal gerne dem Betriebssystem, den Speicher freizugeben:

    static const Constants* instance()
    {
        static Constants* instance = new Constants{};
        return instance;
    }
    

    In diesem Fall wird natürlich der Destruktor von Constants nicht aufgerufen, wenn das Programm beendet wird. Daher sollte die Instanz
    nur Ressourcen halten, die auch tatsächlich bei Programmende vom OS freigegeben werden (bei Speicher ist das im Allgemeinen der Fall).

    Gruss,
    Finnegan



  • Gast3 schrieb:

    Constants::~Constants()
    {
        delete Constants::_instance;
    }
    

    und wird er denn auch aufgerufen? zu sehen im Debugger oder mit printf...

    nein
    Es wird ne aufgerufen



  • Saheb schrieb:

    Gast3 schrieb:

    Constants::~Constants()
    {
        delete Constants::_instance;
    }
    

    und wird er denn auch aufgerufen? zu sehen im Debugger oder mit printf...

    nein
    Es wird ne aufgerufen

    Wie auch? Der Destruktor einer mit new erzeugten Instanz wird im Allgemeinen nur dann aufgerufen, wenn man ohnehin schon ein delete darauf macht.
    Der Code von Gast3 kann also nicht funktionieren und ist - würde er denn funktionieren - bestenfalls ein Bug (double delete).

    Finnegan



  • Saheb schrieb:

    manni66 schrieb:

    ist es jedoch belanglos.

    Warum ist es belanglos? und wann ist einen Leak gefährlich?

    Die statische Variable wird am Programmende zerstört. Dann wird sowieso der vom Prozess verwendete Speicher vom Betriebssystem freigegeben.

    Ansonsten ist das Leak für sich genommen nie gefährlich. Aber jeder Speicher ist endlich und wenn der Destruktor etwas zu tun hätte bleibt dies eben aus.


Anmelden zum Antworten