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

C++ Discussion :

Héritage boucle infinie dans une dll


Sujet :

C++

  1. #1
    Membre du Club
    Inscrit en
    Mars 2006
    Messages
    120
    Détails du profil
    Informations forums :
    Inscription : Mars 2006
    Messages : 120
    Points : 49
    Points
    49
    Par défaut Héritage boucle infinie dans une dll
    Bonjour
    En simplifiant, j'ai crée une dll avec l'héritage suivant :
    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
     
    // Dans Jeu.h
    class CJeu {}
     
    // Dans Joueur.h
    class CJeu;
    class CJoueur 
    {
     CJoueur (CJeu* _jeu);
    }
     
    // Dans JoueurIA.h
    #include "Joueur.h"
    class CJoueurIA:public CJoueur
    {
     CJoueurIA(CJeu* _jeu);
    }
    En appelant le constructeur de CJoueurIA le programme plante à cause d'une boucle infinie. Incompréhensible en assembleur ??? .

    Un post sur un forum parle de précompilation sans explications, de header qui s'entrappelent ... Savez-vous ce qu'ils veulent dire ?
    Voyez-vous d'où peut venir le bug ?

    Merci pour toute réponse

  2. #2
    Membre confirmé
    Inscrit en
    Août 2004
    Messages
    556
    Détails du profil
    Informations forums :
    Inscription : Août 2004
    Messages : 556
    Points : 588
    Points
    588
    Par défaut
    Peut-on voir le contenu de tes constructeurs ?

    Comme tes classes ne possèdent pas de constructeur par défaut, appelles-tu bien le constructeur de Joueur dans JoueurIA ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    CJoueurIA::CJoueurIA( CJeu* _jeu ) :
       CJoueur( _jeu )
    {
    }

  3. #3
    Membre du Club
    Inscrit en
    Mars 2006
    Messages
    120
    Détails du profil
    Informations forums :
    Inscription : Mars 2006
    Messages : 120
    Points : 49
    Points
    49
    Par défaut
    Voici mes constructeurs :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    CJeu::CJeu(void){...}
     
    CJoueur::CJoueur(CJeu* _parent):m_Parent(_parent)
    {...}
     
     
    CJoueurIA::CJoueurIA(CJeu* _parent):CJoueur(_parent)
    {...}

  4. #4
    Membre confirmé
    Inscrit en
    Août 2004
    Messages
    556
    Détails du profil
    Informations forums :
    Inscription : Août 2004
    Messages : 556
    Points : 588
    Points
    588
    Par défaut
    Si tu as une boucle infinie dans le constructeur, et que tu nous montres pas le constructeur, on peut pas vraiment deviner

  5. #5
    Membre du Club
    Inscrit en
    Mars 2006
    Messages
    120
    Détails du profil
    Informations forums :
    Inscription : Mars 2006
    Messages : 120
    Points : 49
    Points
    49
    Par défaut
    Ce n'est pas le code qui est à l'intérieur du constructeur qui provoque la boucle inifinie. C'est à la sortie du constructeur de CJoueurIA.

  6. #6
    Membre éclairé
    Avatar de buzzkaido
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juillet 2004
    Messages
    821
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2004
    Messages : 821
    Points : 734
    Points
    734
    Par défaut
    Quelles opérations fais-tu dans les différents constructeurs ?

    Notamment sur le _parent ?

  7. #7
    Membre confirmé
    Inscrit en
    Août 2004
    Messages
    556
    Détails du profil
    Informations forums :
    Inscription : Août 2004
    Messages : 556
    Points : 588
    Points
    588
    Par défaut
    Si tu as une boucle infinie, tu as une boucle quelque part. Or, dans le code que tu montres, il n'y a aucun signe de boucle. Que veux-tu qu'on cherche comme problème ?
    Ce code ne provoque aucun bug:

    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
     
    #include <iostream>
     
    using namespace std;
     
    class CJeu
    {
    };
     
    class CJoueur
    {
    public:
       CJeu* jeu;
     
       CJoueur( CJeu* _jeu ) :
          jeu( _jeu )
       {
    	   cout << "Constructeur joueur" << endl;
       }
    };
     
    class CJoueurIA : public CJoueur
    {
    public:
       CJoueurIA( CJeu* _jeu ) :
          CJoueur( _jeu )
       {
    	   cout << "Constructeur joueur IA" << endl;
       }
    };
     
    int main()
    {
       CJeu jeu;
       CJoueurIA joueurIA( &jeu );
       CJoueur& joueur = joueurIA;
     
       cout << joueur.jeu << "==" << joueurIA.jeu << endl;
       return 0;
    }

  8. #8
    Membre du Club
    Inscrit en
    Mars 2006
    Messages
    120
    Détails du profil
    Informations forums :
    Inscription : Mars 2006
    Messages : 120
    Points : 49
    Points
    49
    Par défaut
    Dans le constructeur de CJoueur le programme boucle inifiniment sur après

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    m_Logger = new CLogger(Nomdechemin);
    Avec l'architecture suivante :
    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
     
    CJeu::Create()
    {
    J1 = new CJoueurIA(this);
    // Plantage avant
    }
     
    // CJoueurJA appelle le constructeur de CJoueur
    CJoueur::CJoueur(CJeu* _parent, int numjoueur)  // j'avais oublié numjoueur
    {
    char _file_log[32];
    	string _num = ToString(m_NumJoueur).c_str();
    	sprintf(_file_log, "%s\Joueur_%d.log", m_Parent->GetParent()->GetLogDirectoryName().c_str(), m_NumJoueur);
     
    Log = new CLogger(_file_log);  // ne va pas plus loin , boucle infinie en fin de constructeur de CLogger
     
    }
     
    CLogger::CLogger(const std::string& Filename):m_File(Filename.c_str()), filename(Filename)
    {		
    //Rien
    }
    // boucle infine ici
     
    // dans la déclaration de CLogger, en private
    ofstream m_File;
    string filename;
    Le logger est utilisé pour une autre classe avant l'erreur et fonctionne.

    J'espère que ce code vous aidera. merci pour votre aide.

  9. #9
    Membre confirmé
    Inscrit en
    Août 2004
    Messages
    556
    Détails du profil
    Informations forums :
    Inscription : Août 2004
    Messages : 556
    Points : 588
    Points
    588
    Par défaut
    Si ton code respecte exactement cette architecture, ça m'étonnerait très très fortement que tu aies un problème de boucle infinie, tu n'en a littéralement pas.

    Si tu ne peux pas donner plus de code, lance un debugger, tu as sûrement un problème avec l'un des pointeurs que tu gère. (et au passage, rajoute un \ avant Joueur dans ton sprintf, là tu y imprimes l'entier qui représente J et non le caractère \ suivi de J.)

    En même temps, les variables que tu as nommé m_ sont globales ? Car si elles sont (selon une certaine convention obscure) membres de ta classe CJoueur, je vois pas comment tu peux pointer sur quelque chose alors que tu n'as pas initialisé le pointeur, même chose pour l'entier.

  10. #10
    Expert éminent

    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    4 253
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Février 2007
    Messages : 4 253
    Points : 7 618
    Points
    7 618
    Billets dans le blog
    3
    Par défaut
    Moi je soupconne fortement le constructeur de string
    Lors de l'appel Log = new CLogger(_file_log);

    Parceque juste avant on a:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    char _file_log[32];
    	string _num = ToString(m_NumJoueur).c_str();
    	sprintf(_file_log, "%s\Joueur_%d.log", m_Parent->GetParent()->GetLogDirectoryName().c_str(), m_NumJoueur);
    et que si ce code est 'safe', je veux bien me pendre !!

    32 caractères pour stocker un chemin de fichier... c'est un peu court... MAX_PATH à la rigueur (4096 sous windows)... Et si ca dépasse... adieu le 0 terminateur de la chaine... enfin bref....

    Je ne suis même pas sur que le string _num = ToString(m_NumJoueur).c_str(); soit bien raisonnable

    Maintenant je suis très étonné que le compilo ne detecte pas une corruption de pile immédiatement (Visual 'plante' avec un first-chance exception dès le sprintf chez moi, et en tout cas, il me met de gros warnings rouges lors de l'utilistation de sprintf en me disant, c'est pas safe comme fonction, utilise _sprintf(_file_log,32,....)).
    N'oubliez pas de cliquer sur mais aussi sur si un commentaire vous a été utile !
    Et surtout

  11. #11
    Membre émérite
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Points : 2 799
    Points
    2 799
    Par défaut
    Moi je soupconne fortement le constructeur de string
    S'il s'agit bien de std::string, alors oublie tes soupçons. Sauf éventuellement si tu compiles avec borland C++, mais sinon, oublie.

    string _num = ToString(m_NumJoueur).c_str();
    Bizarre ça de passer par .c_str pour le remettre dans une string. Cela dit, ce n'est pas ce qui pose problème.

    Maintenant je suis très étonné que le compilo ne detecte pas une corruption de pile immédiatement (Visual 'plante' avec un first-chance exception dès le sprintf chez moi, et en tout cas, il me met de gros warnings rouges lors de l'utilistation de sprintf en me disant, c'est pas safe comme fonction, utilise _sprintf(_file_log,32,....)).
    Visual ferait mieux de te dire d'utiliser des std::string et boost::format .

    Mais c'est clair que si file_log est trop petit, tu as un débordement de buffer, et là, tu peux avoir tout et n'importe quoi (incluant une boucle infinie). Comme il est alloué sur la pile, tu corromps effectivement bien ta pile.

  12. #12
    Membre du Club
    Inscrit en
    Mars 2006
    Messages
    120
    Détails du profil
    Informations forums :
    Inscription : Mars 2006
    Messages : 120
    Points : 49
    Points
    49
    Par défaut
    Merci white_tentacle et à vous autre.
    C'était bien un débordement du buffer de char.

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

Discussions similaires

  1. Réponses: 29
    Dernier message: 17/06/2006, 13h04
  2. symptome de la boucle infinie dans une requete
    Par ouam81 dans le forum Langage SQL
    Réponses: 8
    Dernier message: 27/05/2005, 12h10
  3. [BP7] Problème chargement de ressource dans une DLL
    Par Alcatîz dans le forum Turbo Pascal
    Réponses: 11
    Dernier message: 26/07/2003, 21h36
  4. PB avec "self" dans une dll
    Par DiJiRiDouS dans le forum Langage
    Réponses: 2
    Dernier message: 21/02/2003, 09h32
  5. [VB6]Passage d'un tableau dans une DLL écrite en delphi
    Par flash dans le forum VB 6 et antérieur
    Réponses: 6
    Dernier message: 20/09/2002, 10h15

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