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

Boost C++ Discussion :

Crash avec boost::function


Sujet :

Boost C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Rédacteur
    Avatar de Bakura
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2005
    Messages
    1 386
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 386
    Par défaut Crash avec boost::function
    Bonsoir !

    Je dispose d'une classe de caméra qui peut mettre à jour la position de la camera de trois manières différentes, selon le type de caméra choisie. J'ai pensé au début à faire trois if :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    if (typeCamera1)
    {
    //
    }
    else if (typeCamera2)
    {
    //
    }
    else
    {
    //
    }
    Toutefois ces fonctions étant assez longues, cela m'aurait fait une fonction UpdatePosition() très très longue. J'ai donc pensé à faire un pointeur de fonction qui appelerait automatiquement la bonne fonction.

    Voici donc la signature de cette fonction :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    boost::function<void ()> updatePositionFunction;
    (variable membre privée)

    Dans le constructeur de la classe, j'attribue la fonction par défaut :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    updatePositionFunction = boost::bind(&Camera::UpdatePositionFPS, this);
    Tout ce code compile correctement, le problème arrive avec la fonction UpdatePosition, qui doit appeler donc la bonne fonction :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    void UpdatePosition ()
    {
       updatePositionFunction; // Compile, mais n'appelle pas la fonction   UpdatePositionFPS
     
       updatePositionFunction(); // Compile, mais crash dès le début de l'application
    }
    D'autre part, est-il possible de traduire ce code sans utiliser boost (qu'avec la STL), tout en gardant une syntaxe pas trop dégueue ?

  2. #2
    Membre Expert

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 294
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 294
    Par défaut
    Salut,

    Il faut que tu testes l'objet fonction avant de l'appeler :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    if( updatePositionFunction )
      updatePositionFunction();
    edit: cela dit non ça devrait être initialisé puisque tu le fais dans le constructeur...

    Sinon non je ne pense pas qu'il y ait une manière simple de parvenir à la même chose sans Boost.

    MAT.

  3. #3
    Membre Expert

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 294
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 294
    Par défaut
    2e tentative...

    Ca là :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    boost::function<void ()> updatePositionFunction;
    Personnellement je l'écris plutôt :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    boost::function0<void> updatePositionFunction;
    Essaye peut-être pour voir ?

    MAT.

  4. #4
    r0d
    r0d est déconnecté
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 288
    Billets dans le blog
    2
    Par défaut
    Bonjour,

    je pense qu'il y a des façons de faire beaucoup plus simple, et plus orientée objet.
    Par exemple, surcharger tout simplement ta fonction updatePosition. Ou encore faire en sorte qu'updatePosition soit une fonction membre de l'interface Camera, cette interface étant implémentée pour chaque type de caméra.

    Ou alors il y a un truc que je n'ai pas compris...

  5. #5
    Rédacteur
    Avatar de Bakura
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2005
    Messages
    1 386
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 386
    Par défaut
    boost::function<void ()> updatePositionFunction;
    et
    boost::function0<void> updatePositionFunction;

    sont identiques d'après la doc de boost, juste que la première écriture est l'écriture recommandée, et la seconde une qui est plus portable, visiblement.

    je pense qu'il y a des façons de faire beaucoup plus simple, et plus orientée objet.
    Par exemple, surcharger tout simplement ta fonction updatePosition. Ou encore faire en sorte qu'updatePosition soit une fonction membre de l'interface Camera, cette interface étant implémentée pour chaque type de caméra.

    Ou alors il y a un truc que je n'ai pas compris...
    Je ne pourrais pas surcharger ma fonction, vu qu'elles ont le même prototype :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    void UpdatePositionFPS ();
    void UpdatePositionFreeFly ();
    void UpdatePosition6DOF ();
    Quant à faire de l'héritage, j'aimerais éviter, j'aimerais garder cette classe assez compacte, et pas dériver trois classes juste pour une seule fonction :/. Là j'avais trouvé un moyen assez classe de régler ce problème, avec un truc comme ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    void SetMode (CAMERA_TYPE type)
    {
       if (type == FPS)
          updatePositionFunction = boost::bind(&Camera::UpdatePositionFPS,               this);
       else if (type == FREEFLY)
          updatePositionFunction = boost::bind(&Camera::UpdatePositionFreeFly, this);
       else
          updatePositionFunction = boost::bind(&Camera::UpdatePosition6DOF, this);
    }
    Et hop, après j'appelle la fonction UpdatePosition indéferemment, qui appelera directement la bonne fonction. Ca m'évite de faire trois ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    void SetMode (CAMERA_TYPE type)
    {
       if (type == FPS)
          UpdatePositionFPS();
       else if (type == FREEFLY)
          UpdatePositionFreeFly();
       else
          UpdatePosition6DOF();
    }
    et d'avoir à faire à chaque fois des if qui, vraisemblablement, ne changeront qe très peu souvent au cours du programme.

    Mat007 >
    edit: cela dit non ça devrait être initialisé puisque tu le fais dans le constructeur...
    Oui oui, j'allais quand même pas me faire avoir si facilement

  6. #6
    Alp
    Alp est déconnecté
    Expert confirmé

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Par défaut
    Il n'existe pas de manière plus simple à ma connaissance.
    Ce sera toujours, dans le meilleur des cas, équivalent.

    En débuggant, tu obtiens quoi comme infos sur
    - le boost::function
    - l'endroit exact où s'arrête le programme (l'appel de la fonction ou le code qu'elle contient ?)
    ?

  7. #7
    Rédacteur
    Avatar de Bakura
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2005
    Messages
    1 386
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 386
    Par défaut
    Personne n'a d'idée ?

  8. #8
    Membre Expert

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 294
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 294
    Par défaut
    Fais un code minimal qui reproduit le problème qu'on puisse le tester pour voir ?

    MAT.

  9. #9
    Rédacteur
    Avatar de Bakura
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2005
    Messages
    1 386
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 386
    Par défaut
    Hum... C'est pas clair. J'ai écrit ce code minimal :
    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
     
    class Foo
    {
    	public:
    		// Constructeur
    		Foo ()
    		{
    			// Initialise le pointeur de fonction à la fonction A
    			func = boost::bind(&Foo::A, this);
    		}
     
    		// Fonction A
    		void A ()
    		{
    			std::cout << "A est appele ?";
    		}
     
    		// Fonction B
    		void B ()
    		{
    			std::cout << "B est appele";
    		}
     
    		// Fonction qui appelle la fonction adéquate
    		void CallFunction ()
    		{
    			// Devrait appeler A
    			func();
    		}
     
    	private:
    		boost::function<void ()> func; // Identique à boost::function0<void> func
     
    };
     
    int main()
    {
    	Foo object;
    	object.CallFunction();
     
    	return EXIT_SUCCESS;
    }
    et là, ça fonctionne . Très étonnant. Pourtant j'ai juste recopié le cas de l'autre .

    EDIT : j'avoue ne pas comprendre. Dans mon main, mon objet Camera est une variable globale. Là, je créé un autre objet Camera non globale, sans rien appeler d'autre que le constructeur, et là ça marche .

    EDIT 2 : bon, tout en gardant mon unique variable globale, et en incluant une fonction Bind en plus qui ne refait que ce que le constructeur fait (c'est à dire ça : updatePositionFunction = boost::bind(&Camera::UpdatePositionFPS, this);

    Et en appelant cette fonction Bind dès le début, plus de soucis, comme si cela plantait dans le constructeur .

    EDIT 3 : bon, encore autre chose. Sans aucune fonction bind, si je définit le constructeur DIRECTEMENT dans la classe, comme dans le petit exemple plus haut, ça marche. Si je définie le constructeur inline et que je définie le constructeur dans le fichier hpp mais en dehors de la classe, ça marche aussi. Par contre dès que je définie le constructeur dans le .cpp, ça plante .

    Est-ce un soucis de boost ?

  10. #10
    Rédacteur
    Avatar de Bakura
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2005
    Messages
    1 386
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 386
    Par défaut
    Je dois avouer que je ne comprends rien du tout à ce problème. J'ai refait un autre code minimal en séparant fichier d'en-tête et fichier d'implémentation, sans aucune fonction inline, avec une variable globale, et là ça fonctionne. Par contre, quand c'est mon programme, ça plante ...

    EDIT : bon, j'ai refait des tests, et ça vient peut-être de SFML... Je ne veux pas l'accuser direct, mais c'est bizarre. En effet, j'ai fait un petit test dès l'execution du programme, dans les premières lignes. J'ai testé ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    Camera myCamera; // Variable globale (juste globale pour la facilité ici)
     
    int main()
    {
       // Ici, le constructeur de Camera est déjà appelé
       myCamera.UpdatePosition; // Cette fonction appelle juste l'objet de boost
    }
    Dans ce cas là, la bonne fonction (UpdatePositionFPS) est bien appelée. Par contre, si je change en faisant ça :

    sf::RenderWindow App;
    Camera myCamera;

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    int main()
    {
    	// On commence par créer une fenêtre et un contexte valide pour OpenGL
    	App.Create (sf::VideoMode (800, 600), "Hola a todos");
    	App.ShowMouseCursor (false);
    	App.SetFramerateLimit (60);
     
    	myCamera.UpdatePosition();
    }
    Là, ça ne fonctionne plus, et la fonction n'est pas appelée. Je vais essayer de me renseigner auprès de Laurent voir s'il n'y a pas quelque chose qui coince.

    EDIT 2 : ok, j'ai fait un code minimal, le conflit vient bien avec SFML. Je me renseigne auprès de Laurent.

  11. #11
    Rédacteur
    Avatar de Bakura
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2005
    Messages
    1 386
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 386
    Par défaut
    Bon, j'ai résolu le soucis... C'était évidemment de ma faute... En fait, j'utilise une version bêta de la SFML, et le dossier Include n'était pas à jour, et il fallait utiliser le dossier src, qui contenait les headers mis à jour, maintenant ça marche.

    Bref, tout ça à cause de ça :p.

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

Discussions similaires

  1. Réponses: 19
    Dernier message: 16/09/2008, 11h44
  2. [boost] Problème avec boost::function
    Par Bakura dans le forum Boost
    Réponses: 3
    Dernier message: 22/03/2007, 20h08
  3. probleme de compilation avec boost
    Par doof dans le forum Bibliothèques
    Réponses: 7
    Dernier message: 07/06/2005, 21h38
  4. Calculer un inverse de matrice avec boost?
    Par Clad3 dans le forum Bibliothèques
    Réponses: 6
    Dernier message: 02/06/2005, 18h38
  5. probleme avec boost et devcpp
    Par Krost dans le forum Dev-C++
    Réponses: 12
    Dernier message: 02/01/2005, 19h11

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