IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage C++ Discussion :

std::map access violation


Sujet :

Langage C++

  1. #1
    Membre habitué
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2011
    Messages
    107
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Septembre 2011
    Messages : 107
    Points : 132
    Points
    132
    Par défaut std::map access violation
    Bonsoir,

    J'ai une classe nommée Hermes qui est un singleton.
    Elle est globale à tout le programme et est initialisée à NULL.
    Cette classe comporte un attribut public qui est un manager de ressources (ici des sf::Texture).
    On la nommera TextureManager.
    TextureManager possède un attribut private qui est le suivant :
    std::map<std::string, sf::Texture*> Textures;

    La classe Hermes est initialisée tel que :
    Hermes *Hermes::_instance = NULL;


    Dans mon TextureManager j'ai une méthode qui va effectuer un find sur le std::map Textures
    C'est là que ça pète.

    J'ai une access violation :
    0xC0000005: Access violation reading location 0x00000008


    Suite à mes recherches, le problème viendrait du fait que le std::map n'est pas correctement initialisé.
    Je ne vois vraiment pas ce qu'il faut faire par contre. Comment initialiser ce std::map ?
    Je n'ai jamais rien fait d'autre que de déclarer un std::map et de m'en servir, sans étape préalable...


    J'espère avoir été clair dans l'exposition de mon problème.
    Au besoin, je peux vous montrer le code des classes que vous souhaitez voir.
    D'avance merci pour votre aide

    Bonne soirée


    EDIT : Ajout du code épuré et condensé au possible :
    Main.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
     
    #include "Hermes.hpp"
     
    int main()
    {
    	// Hermes
    	Hermes *Hermes = Hermes::GetInstance();
     
    	engine Engine;
    	// main loop...
    	while(engine.isRunning())
    	{
    		engine.Update();
    	}
    	Hermes->Kill();
        return 0;
    }
    Hermes.hpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    #include "TextureManager.hpp"
     
    class Hermes
    {
    public:
    	static Hermes* GetInstance();
    	static void Kill();
     
    	TextureManager TxMgr;
    private:
    	Hermes();
    	~Hermes();
     
    	static Hermes* _instance;
    };
    Hermes.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
     
    #include "Hermes.hpp"
     
    Hermes *Hermes::_instance = NULL;
     
    Hermes::Hermes(){}
    Hermes::~Hermes(){}
     
    Hermes* Hermes::GetInstance()
    {
    	if(_instance != NULL)
    		_instance = new Hermes();
    	return _instance;
    }
     
    void Hermes::Kill()
    {
    	if(_instance != NULL)
    	{
    		delete _instance;
    		_instance = NULL;
    	}
    }
    TextureManager.hpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    class TextureManager
    {
     
    private:
    	std::map<std::string, sf::Texture*> Textures;
    	bool Search(const std::string &link);
    	bool Add(const std::string &link);
     
    public:
    	TextureManager();
    	~TextureManager();
    	sf::Texture& Get(const std::string &link);
    	void Delete(const std::string &link);
    };
    TextureManager.hpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
     
    TextureManager::TextureManager(){}
     
    TextureManager::~TextureManager()
    {
    	std::map<std::string, sf::Texture*>::iterator it;
    	for(it = Textures.begin(); it != Textures.end(); it++)
    		delete it->second;
    }
     
    bool TextureManager::Search(const std::string &link)
    {
    	std::map<std::string, sf::Texture*>::iterator it;
     
    	/* C'est ici que ça fail ... */
    	it = Textures.find(link);
    	/* ------------------------- */
     
    	if(it == Textures.end())
    		return false;
    	return true;
    }
     
    bool TextureManager::Add(const std::string &link)
    {
    	sf::Texture *tmp = new sf::Texture;
    	if(!tmp->loadFromFile("assets/textures/" + link))
    	{
    		delete tmp;
    		return false;
    	}
     
    	this->Textures.insert(std::make_pair(link, tmp));
    	return true;
    }
     
    sf::Texture& TextureManager::Get(const std::string &link)
    {
    	if(!Search(link))
    		this->Add(link);
     
    	return *Textures.find(link)->second;
    }
     
    void TextureManager::Delete(const std::string &link)
    {
    	std::map<std::string, sf::Texture*>::iterator it;
     
    	it = Textures.find(link);
    	if(it != Textures.end())
    	{
    		delete it->second;
    		Textures.erase(it);
    	}
    }
    Dans la méthode Update qui est dans le Main, j'essaie donc de récupérer un sf::Texture en faisant ça :
    sf::Texture tex = Hermes::GetInstance()->TxMgr.Get("bg");


    Voilà, j’espère que ce n'est pas trop long...

  2. #2
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 611
    Points
    30 611
    Par défaut
    Salut,

    Déjà, l'idée même du singleton, c'est, disons le carrément, moyen moyen.

    En effet, même si l'on peut considérer qu'il faut charger les textures très rapidement (au lancement de l'application ) le nombre d'endroits où tu devras y accéder reste, malgré tout, relativement restreint.

    Dans le pire des cas, tu ne devrais pas avoir à accéder aux différentes textures à plus de deux ou trois endroits dans le code. Si ce n'est pas le cas, c'est, sans doute, que tu as "foiré" quelque part dans ta conception

    La meilleure manière de t'assurer qu'un objet n'est créé que de manière unique reste, toujours, de veiller à ... ne créer qu'une seule instance de cet objet

    Ainsi, tu pourrais parfaitement envisager le fait de créer un seul membre de type std::map<std::string, sf::Texture*> au niveau de ta classe "principale" (application ) et de le transmettre par référence aux différentes classes qui en auraient besoin, comme "TextureLoader" (pour les charger ) ou la classe qui prend en charge l'affichage de ta vue

    A priori, tu ne devrais pas avoir besoin d'accéder aux différentes textures ailleurs

    Ceci étant dit, il existe plusieurs solutions pour implémenter le pattern singleton, et que nous ne pourrons réellement t'aider qu'une fois que l'on saura exactement quelle solution tu as envisagé.

    Si tu nous montrais un peu de code, nous aurions beaucoup plus facile à te répondre

    Comme tu as édité ton message pendant que j'écrivais ma prose... :

    Réfléchis un peu à ce que tu fais dans
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    Hermes* Hermes::GetInstance()
    {
    	if(_instance != NULL)
    		_instance = new Hermes();
    	return _instance;
    }
    Heuuu... si _instance est différent de NULL, c'est qu'il existe déjà ... Cherchez l'erreur
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  3. #3
    Membre habitué
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2011
    Messages
    107
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Septembre 2011
    Messages : 107
    Points : 132
    Points
    132
    Par défaut
    Salut

    Quand j'ai vu mon erreur... Damned.
    Enfin bref, merci.

    Concernant mon TextureManager je vais tenter d'expliquer ce choix.

    Dans le pire des cas, tu ne devrais pas avoir à accéder aux différentes textures à plus de deux ou trois endroits dans le code. Si ce n'est pas le cas, c'est, sans doute, que tu as "foiré" quelque part dans ta conception
    En fait chaque composant (que ce soit la carte, les ennemis, le personnage, les tirs, le décor) se charge lui même de son propre affichage. Il stock donc lui même ses sf::Sprite dont les Textures sont référencés vers le Manager.
    J'ai parlé de cette architecture sur le forum de la SFML et il apparaît qu'elle n'est pas dénué de sens et couramment utilisée.

  4. #4
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 611
    Points
    30 611
    Par défaut
    Je ne dis pas que ce n'est pas couramment utilisé, je dis que le singleton est un "anti patern" qui devrait être évité autant que possible...

    Tout, ou à peu près, est composé de texture, soit.

    Mais, en vertu du principe de la responsabilité unique, si tu donnes la responsabilité de se tracer à tout, tu ne devrais plus pouvoir leur en donner d'autre, or, tout a "autre chose à faire", sans doute de bien plus intéressant, que simplement de se tracer.

    Par contre, comme tu regroupe, vraisemblablement, l'ensemble de ce qui constitue ta scène dans une collection quelconque, tu peux très facilement avoir un visiteur qui va parcourir l'ensemble de ces éléments, leur demander la (les) identifiant(s) de la (des) texture(s) dont ils sont composés et leur position, et se charger, à un seul endroit dans le code, de récupérer la / les texture(s) sur base de l'identifiant obtenu pour l'afficher au bon endroit.

    En effet, que tu doive afficher un mur, un arbre, une arme, un sort quelconque ou un joueur, le principe reste toujours le même pour l'afficher...

    En dégageant la responsabilité de l'affichage vers une classe qui ne s'occupe que de cela, tu pourras en plus respecter un autre principe d'Xtrem programming que l'on rappelle régulièrement : DRY (Don't Repeat Yourself, ou, si tu préfères en francais : ne te répètes pas).

    Le gros avantage que tu tireras de tout cela au final, c'est que tu ne devras plus parcourir l'ensemble des classes de ton projet si, à un moment quelconque, il y a un problème avec l'affichage: tout sera centralisé à un endroit bien particulier, et tu auras donc beaucoup plus facile à faire évoluer ou à améliorer les choses

    Emmanuel Deloguet a écrit un article particulièrement intéressant sur la problématique du singleton, je ne peux que te conseiller d'y jeter un coup d'oeil
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

Discussions similaires

  1. Accession aux std::map triées ?
    Par Matthieu Brucher dans le forum SL & STL
    Réponses: 5
    Dernier message: 18/11/2005, 15h44
  2. Réponses: 7
    Dernier message: 22/02/2005, 14h07
  3. Trier un std::map selon les valeurs plutot que les clés
    Par dj.motte dans le forum SL & STL
    Réponses: 2
    Dernier message: 13/11/2004, 22h54
  4. [DELPHI][PROECEDURES STOCKES] Access violation
    Par All Jinx dans le forum Bases de données
    Réponses: 6
    Dernier message: 14/05/2004, 16h57
  5. Réponses: 3
    Dernier message: 22/05/2002, 10h37

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo