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 :

Appel de fonction virtuelle pure


Sujet :

Langage C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé Avatar de Darktib
    Profil pro
    Inscrit en
    Mai 2009
    Messages
    66
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2009
    Messages : 66
    Par défaut Appel de fonction virtuelle pure
    Bonjour,

    J'ai deux classes, dont l'une gère l'autre (code source ci-après). Il se trouve que lors de la destruction de la première classe, j'ai un appel à une fonction virtuelle pure. Je tiens à préciser que j'ai cherché sur internet un solution éventuelle à mon problème, mais je n'ai rien trouvé qui corresponde vraiment à mon problème.

    Donc voici le code:

    action_manager.h:
    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
    #ifndef _ACTIONS_LIST_INCLUDED_
    #define _ACTIONS_LIST_INCLUDED_
    #include <list>
    #include "systemLists.h"
    #include "..\devicesStruct.h"
     
    class Entity;
    class Action;
     
    class ActionsList
    {
    	public:
    		//! Constructeur et destructeur
    		ActionsList(SDevices* devs, Entity* owner);
    		~ActionsList();
     
    		//! Gestion des actions
    		void addAction(ENUM_ACTION_INDEXES_LIST action);
    		void popAction();
    		void clear();
     
    		//! Mise à jour
    		void execute(float deltaT);
     
    		//! Informations
    		int getActionCount();
    		SDevices* getDevices();
     
    	private:
    		void activateFirstAction();
    		std::list<Action*> actList;
    		Entity* actionsOwner;
    		int totalActions;
    		SDevices* devices;
    };
     
    #endif // _ACTIONS_LIST_INCLUDED_
    action_manager.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
    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
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    #include "ActionsBase.h"
    #include "ActionsList.h"
    #include "..\Entity\Entity.h"
     
    //! Actions de base
    void Action::setEntityAnimation(unsigned int start, unsigned int end)
    {
    	float num = object->getSceneNode()->getFrameNr();
    	object->setAnimationRange(start,end);
    	if(num>=start && num<=end) object->getSceneNode()->setCurrentFrame(num);
    }
     
    //! Constructeur et destructeur
    ActionsList::ActionsList(SDevices* devs, Entity* owner)
    :actionsOwner(owner),totalActions(0),devices(devs)
    {
    }
    ActionsList::~ActionsList()
    {
    	printf("Clearing...\n");
    	clear();
    	printf("Cleared !\n");
    }
     
    //! Gestion des actions
    void ActionsList::addAction(ENUM_ACTION_INDEXES_LIST action)
    {
    	if(baseActions[(int)action])
    	{
    		Action* act = baseActions[(int)action]->cloneType();
    		act->manager = this;
    		act->object = actionsOwner;
    		actList.push_back(act);
    		totalActions++;
    		act->OnActionCreation();
    		if(totalActions==1)
    			activateFirstAction();
    	}
    }
    void ActionsList::popAction()
    {
    	if(actList.begin() != actList.end())
    	{
    		Action* act = *actList.begin();
    		act->OnActionDeletion();
    		delete act;
    		actList.erase(actList.begin());
    		totalActions--;
    		activateFirstAction();
    	}
    }
    void ActionsList::clear()
    {
    	while(actList.begin() != actList.end())
    		popAction();
    }
     
    //! Mise à jour
    void ActionsList::execute(float deltaT)
    {
    	if(actList.begin() != actList.end())
    		(*(actList.begin()))->exec(deltaT);
    	else addAction(EAIL_IDLE);
    }
     
    //! Informations
    int ActionsList::getActionCount()
    {
    	return totalActions;
    }
    SDevices* ActionsList::getDevices()
    {
    	return devices;
    }
     
    //! Privé
    void ActionsList::activateFirstAction()
    {
    	if(actList.begin() != actList.end())
    	{
    			Action* act = *actList.begin();
    // Voici la fonction qui plante : 
    			act->OnActionActivation();
    	}
    }
    L'appel à la fonction OnActionActivation plante uniquement lorsque l'actionlist est détruite. J'ai fait le test, en cours d'exécution + de 5000 appels de cette fonction ne font absolument aucune erreur...
    Par contre, quand on l'appelle depuis le destructeur d'ActionList (via clear() -> popAction() ), ca plante dès la première exécution...

    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
     
    #include "..\devicesStruct.h"
    #include "systemLists.h"
    #include "ActionsList.h"
    #include "..\type.h"
    #include <vector>
     
    class Entity;
     
    struct Action
    {
    	//! La classe dont dépendent les actions
    	ActionsList* manager;
    	Entity* object;
     
    	//! Les données de l'action
    	std::vector<VoidValue> data;
     
    	//! Destructeur virtuel
    	virtual ~Action() {}
     
    	//! Slots
    	virtual void OnActionCreation() =0;
    	virtual void OnActionActivation() =0;
    	virtual void OnActionDeletion() =0;
     
    	//! Fonctions principales
    	virtual void exec(float deltaT) =0;
    	virtual Action* cloneType() =0;
    	virtual void escapeIfOtherActionsInList()
    	{ if(manager->getActionCount()>1) manager->popAction(); }
    	virtual void finish()
    	{ manager->popAction(); }
    	virtual void setEntityAnimation(unsigned int start, unsigned int end);
     
    	//! RTTI
    	virtual ENUM_ACTION_INDEXES_LIST getType() =0;
    };
    Toutes les fonctions sont bien réimplémentées dans les classes filles...
    Et j'obtient l'erreur meme si je met
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    	virtual void OnActionActivation() {printf("Act!\n");}
    au lieu de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    	virtual void OnActionActivation() =0;
    dans la classe de base...


    Quelqu'un aurait il une idée ?

    Merci d'avance.

  2. #2
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Bonjour et bienvenu,
    Je dois avouer que je ne vois rien qui saute aux yeux expliquant ton pb.
    As tu mis un point d'arrêt dans clear pour voir les différents pointeurs retournés ?
    J'aurais rajouté une trace dans les destructeur de Action pour voir s'ils ne sont pas détruit 2 fois ?


    Ensuite, quelques remarques :
    1/ tu peux utiliser pop_front qui est plus parlant que erase dans ton cas ;
    2/ J'aurais fais le delete après le erase/pop_front
    3/ C'est bizarre d'avoir une méthode 'popAction' alors que ta liste se comporte comme une FIFO et non comme une stack (qui existe en std par ailleurs).
    4/ Pourquoi ne pas utiliser des pointeurs intelligents dans la liste ?

  3. #3
    Membre éclairé Avatar de Darktib
    Profil pro
    Inscrit en
    Mai 2009
    Messages
    66
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2009
    Messages : 66
    Par défaut
    J'ai testé avec des pointeurs, et ils sont tous supprimés une fois. De plus, en mettant un message dans le pseudo destructeur des actions (OnActionDeletion, le vrai destructeur ne sert a rien car il n'y a rien à supprimer), je vois que chaque destructeur est appelé une fois. Si l'objet était supprimé deux fois, j'aurais eu une violation d'accès mémoire, plus facile à corriger...

    Sinon pour les remarques:
    1/ Merci de la suggestion, je vais changer ca.
    2/ Idem
    4/ Les Actions ne sont utilisées que par cette classe, aucune autre classe ne peut les utiliser. De plus, toute action crée n'appartient qu'a la même actionslist, et doit etre détruite si jamais la liste n'en a plus besoin. C'est pourquoi je pense que des pointeurs intelligents ne sont pas très utiles ici.

    J'ai fait d'autres tests, en sortant l'appel de clear() du destructeur. C'est l'entité qui possède la liste d'actions qui appelle le clear() de la liste, puis la supprime après. Résultat : aucun changement...

  4. #4
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Il y a peut être un problème d'intégrité de ta liste ou d'un de ses objets (un écrasement ?). As-tu pisté de ce côté ?

  5. #5
    Membre éclairé Avatar de Darktib
    Profil pro
    Inscrit en
    Mai 2009
    Messages
    66
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2009
    Messages : 66
    Par défaut
    Je vais chercher, mais ca serait bizarre...
    En effet, ce crash n'est pas aléatoire.

    Sinon j'ai appliqué tes deux premières suggestions, aucun changement a part un code plus lisible (c'est déjà ca)

    edit : Les pointeurs sont apparemment bons, j'ai testé avec la fonction getType() des Actions, et là aucun problème.

  6. #6
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Le problème - si t'as un écrasement - c'est qu'il peut très bien y avoir des choses qui se comportent bien et d'autres non. Au vu du code que tu fournis, je ne vois pas de raison évidente pour qu'il y aie un problème spécifiquement sur les méthodes virtuelles pures. C'est pour ça que j'ai tendance à penser que le bug est ailleurs...

    [EDIT] : peux-tu poser le code de la première action détruite ?

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 4
    Dernier message: 11/10/2013, 12h08
  2. Réponses: 15
    Dernier message: 07/06/2010, 20h25
  3. Fonction appelant une fonction virtuelle pure
    Par oodini dans le forum C++
    Réponses: 12
    Dernier message: 19/09/2008, 08h24
  4. Réponses: 2
    Dernier message: 05/03/2006, 19h29
  5. Compilation avec des fonctions virtuel pure
    Par vanitom dans le forum C++
    Réponses: 4
    Dernier message: 16/12/2005, 14h37

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