Forum de la communauté SFML

Aide => Général => Discussion démarrée par: Koseki le Mai 10, 2018, 10:39:13 pm

Titre: Delete qui fait planter le programme
Posté par: Koseki le Mai 10, 2018, 10:39:13 pm
Bonjour!

Petit soucis aujourd'hui...
J'ai créer un logger pour écrire des messages dans une console ou un fichier.
Mais j'ai un petit problème! Lorsque je veux affecter un nouveau logger(pour switcher entre différents fichiers ou la console) mon programme plante.
Après quelques recherches, je me suis aperçu que c'est mon delete qui fait planter mon programme!

Le truc étrange, c'est qu'on rentre deux fois d'affiler dans la fonction destroy()... et à chaque fois, le delete ne fonctionne pas.

Quelqu'un aurait une idée d'où ça pourrais venir?

Voici mon retour dans la console:
On change le logger
Destruction de l'objet...
Objet détruit
Objet re-définit
Teste
On change le logger
Destruction de l'objet...
Destruction de l'objet...

Voici le code dans mon main:
AbstractLogger::setLogger(new ConsoleLogger());
AbstractLogger::log() << "Teste \n";

AbstractLogger.hpp:
#ifndef DEF_ABSTRACT_LOGGER
#define DEF_ABSTRACT_LOGGER

#include <iostream>

class AbstractLogger
{
    public:
        AbstractLogger();
        virtual ~AbstractLogger();

        static void setLogger(AbstractLogger* logger); // Permet de modifier le logger à utiliser
        static AbstractLogger& log(); // Renvoie une référence sur le logger actuel

        AbstractLogger& operator <<(const std::string& message); // Permet de logger ce qu'on veut en utilisant la syntaxe du C++(grace à la surcharge de l'opérateur <<)

    private:
        static void destroy(); // Détruit l'instance du logger, private pour éviter de l'appeler n'importe où

        virtual void write(const std::string& message) = 0; // Fonction purement virtuelle pour éviter d'instancier cette classe directement, elle nous servira à lancer l'écriture

        static AbstractLogger* m_instance; // Pointeur sur le logger actuel (singleton)
};

#endif // DEF_ABSTRACT_LOGGER

AbstractLogger.cpp
#include <iostream>
#include "../../include/Logger/AbstractLogger.hpp"
#include "../../include/Logger/ConsoleLogger.hpp"

AbstractLogger* AbstractLogger::m_instance = nullptr; // Bien sur, on initialise notre instance à nullptr

AbstractLogger::AbstractLogger()
{

}
AbstractLogger::~AbstractLogger()
{
    destroy();
}

void AbstractLogger::setLogger(AbstractLogger* logger)
{
    std::cout << "On change le logger" << std::endl;
    destroy();
    m_instance = logger;
    std::cout << "Objet re-définit"<< std::endl;
}
void AbstractLogger::destroy()
{
    std::cout << "Destruction de l'objet..."<< std::endl;
    delete m_instance;
    std::cout << "Objet détruit"<< std::endl;
    m_instance = nullptr;
}

AbstractLogger& AbstractLogger::log()
{
    return *m_instance;
}

AbstractLogger& AbstractLogger::operator <<(const std::string& message)
{
    write(message);
    // On renvoie notre instance pour pouvoir chaîner les appels à << pour garder le même fonctionnement que std::cout <<
    return log();
}
 

ConsoleLogger.hpp
#ifndef DEF_CONSOLE_LOGGER
#define DEF_CONSOLE_LOGGER

#include <iostream>
#include "AbstractLogger.hpp"

class ConsoleLogger : public AbstractLogger
{
    public:
        ConsoleLogger();
    protected:
        virtual void write(const std::string& message);
};

#endif // DEF_CONSOLE_LOGGER
 

ConsoleLogger.cpp
#include <iostream>
#include "../../include/Logger/ConsoleLogger.hpp"

ConsoleLogger::ConsoleLogger()
{

}

void ConsoleLogger::write(const std::string& message)
{
    std::cout << message;
}

 

Pour tester le bon fonctionnement de mon logger, j'ai rajouter ce code dans le destructeur d'une de mes classes(pour tester l'écriture dans un fichier suite à une erreur, mais pour mes testes, je suis passer à l'écriture dans la console)
AbstractLogger::setLogger(new ConsoleLogger());
AbstractLogger::log() << "ALL GREEN";
C'est pour cela que nous avons 2 changements de logger.

J'ai essayer d'enlever le delete et l'application fonctionne niquel...

Merci à tous ceux qui pourront m'aider!
Titre: Re: Delete qui fait planter le programme
Posté par: kimci86 le Mai 11, 2018, 12:35:24 am
Le problème est que destroy appelle le destructeur de l'instance via un delete qui lui-même appelle destroy.

Je recommande de stocker l'instance dans un std::unique_ptr, ce qui libérera la mémoire automatiquement.
Titre: Re: Delete qui fait planter le programme
Posté par: Laurent le Mai 11, 2018, 08:07:33 am
Et quel est le rapport avec SFML ? Il y a des forums plus spécialisés pour les questions de C++ ; ici on essaye dans la mesure du possible de rester concentrés sur SFML ;)
Titre: Re: Delete qui fait planter le programme
Posté par: Koseki le Mai 11, 2018, 11:18:32 am
Le problème est que destroy appelle le destructeur de l'instance via un delete qui lui-même appelle destroy.

Je recommande de stocker l'instance dans un std::unique_ptr, ce qui libérera la mémoire automatiquement.
Ah mais oui, pourquoi je n'y ait pas pensé >_> Merci kimci86!

Et quel est le rapport avec SFML ? Il y a des forums plus spécialisés pour les questions de C++ ; ici on essaye dans la mesure du possible de rester concentrés sur SFML ;)
Oui, désolé Laurent, j'éviterais à l'avenir les questions hors SFML :)