Forum Programmation.c++ problème d'acces à une méthode

Posté par  (site web personnel) .
Étiquettes : aucune
0
7
avr.
2005
Bonjour !

J'ai un petit probleme... (enfin pour dire vrai, j'ai passe des heures et des heures a essayer de le resoudre sans succes): j'ai les classes suivantes:

equation {
public:
virtual double f(void);
.....
}

et inductance:equation {
public:
double f(void)
.....
}

ainsi que d'autres classes comme inductance qui heritent de "equation". Le probleme que j'ai, c'est que bizarement, quand une methode de "inductance" essaye d'appeller "f()", mon programme segfault... quand une autre classe, construite comme "inductance" appelle son propre "f()", ça marche... quand je force "inductance::f()" dans ma methode (faisant partie de "inductance"), ça marche aussi...

Donc en gros, lorsque j'appelle "f()" depuis "inductance", cela ne va pas chercher la fonction "f()" dans la classe "inductance" et plante...

De quoi cela peut-il venir ?? En sachant que les autres classes heritant de "equation" fonctionnent parfaitement.

Merci !
Mathias
  • # Des détails, des détails :-)

    Posté par  . Évalué à 2.

    Tu crois que tu pourrais mettre un peu plus de détails stp, du genre tes fichiers .h et éventuellement les .cpp ? Parce que là, apparemment, le problème a l'air de venir de la classe inductance, mais bon ...
    • [^] # Re: Des détails, des détails :-)

      Posté par  (site web personnel) . Évalué à 1.

      En fait, je n'ai pas mis le detail des fichiers, car ceci est une version suivante d'un programme qui a deja marché... (version 0.9, et la version 0.8 marchait bien). J'ai essayé de mettre les fichiers inductance.h et inductance.cpp, ainsi que equation.h et equation.cpp dans l'ancienne version, et cela marche parfaitement ! Donc en fait, il semble qu'une modification de classes externes (et "equation" n'herite de rien) ait fait que cela ne marche plus, et seulement pour "inductance" et pas pour les autres classes qui sont semblables a "inductance"... pour ce qui est du code, voila ce que cela donne:

      class inductance : public equation
      {
      public:
      double L;
      double C;
      QString message;
      public:
      inductance();
      int setType(int choice);
      double f(void);
      void CalculateLandC(void);
      double parallele_wires(void);
      double coaxial_line(void);
      double strip_line(void);
      double converging_line(void);
      double disks(void);
      double rectangular_coil(void);
      double helix(void);
      double L2C(void);
      double C2L(void);
      private:
      int setTabKsh(void);
      int setTabKl(void);
      int setTabN(void);
      int setTabG(void);
      double Ksh(double a);
      double Kl(double a);
      double Ns(double a);
      double Gs(double a);
      private:
      enum InductanceType {ParalleleWires, CoaxialLine, StripLine, ConvergingLine, Disks, RectangularCoil, Helix};
      InductanceType type;
      tabulation tab_Ksh;
      tabulation tab_Kl;
      tabulation tab_N;
      tabulation tab_G;
      };

      et
      class equation
      {
      public:
      QString message;
      enum FieldFlags {GRT_INDEX_MASK=127, IS_GRT_THAN=128, IS_HIDDEN=256, IS_INTEGER=512, IS_POSITIVE=1024, IS_NEGATIVE=2048};
      public:
      virtual ~equation() { }
      virtual double f(void); //in fact, F must be f(x)-y=0, so solving it for 0 finds x such as y=f(x)
      double df(int index_deri);
      int Newton(int index_to_solve,double guess);
      virtual int solve(int index_to_solve);
      public:
      double parameters[MAX_EQ_PARAMETERS];
      double guess[MAX_EQ_PARAMETERS]; //initial values of the parameters for the solvers
      int constraints[MAX_EQ_PARAMETERS]; //solving constraints
      protected:
      short int nb_params;
      };


      Evidement, dans les cpp associés, je déclare mes fonctions de la façon suivante:
      double inductance::f(void) {}

      Mathias
  • # quelques suggestions.

    Posté par  (site web personnel) . Évalué à 1.

    Je ne sais pas ce qui ne va pas, mais juste une paire de remarques :

    - on ne sait pas à priori quel est le type d'héritage utilisé (j'ignore s'il y a une norme ou si ça dépend des implémentations). Personnellement, j'aurais écrit :

    class inductance: public equation {

    - j'aurais redéclaré virtual inductance::f (la encore je ne sais pas si c'est indispensable).

    Si ce n'est pas cela, soit l'erreur vient d'une ligne de code non citée, soit je ne vois pas ce qui devrait me crever les yeux.
    • [^] # Re: quelques suggestions.

      Posté par  (site web personnel) . Évalué à 2.

      non, l'erreur ne peut venir de là.

      mettre l'accolade juste après ne change rien du tout. C'est un choix mais le compilateur ne va pas faire le difficile pour ça.

      Pour ce qui est du deuxième, on doit remettre le mot virtual dans les classes dérivées de cette classe, on souhaite pouvoir la redéfinir. Sinon si c'est une classe feuille (pas de sous classe), mettre ou ne pas mettre virtual ne changera rien du tout.
      • [^] # Re: quelques suggestions.

        Posté par  (site web personnel) . Évalué à 2.

        arf, je me suis trompé et j'ai mal écrit, je reprend donc :

        Pour ce qui est du deuxième point, on doit remettre le mot virtual devant la fonction, si dans les classes dérivées de cette classe, on souhaite pouvoir redéfinir cette fonction. Sinon si c'est une classe feuille (pas de sous classe), mettre ou ne pas mettre virtual ne changera rien du tout.
  • # Segfault ?

    Posté par  . Évalué à 2.

    Es-tu sûr qu'il s'agisse bien d'une segfault déjà, et pas d'une division par zéro ou d'un « Abort » dù à une exception non rattrapée ?

    Ensuite, elle est censée faire quoi ta fonction f ? Parce qu'une fonction mathématique sans inconnue (type void), c'est pas courant. A mon avis, le problème se situe dans le code de ta fonction.

    Mets le tout en GPL et tu pourras bénéficier de l'aide de la communauté ! :-)
    • [^] # Re: Segfault ?

      Posté par  . Évalué à 1.

      Ce qui expliquerait la différence de comportement entre deux architectures ? Peut-être. Sans l'implémentation, ça va être dur de diagnostiquer quoique ce soit ...
    • [^] # Re: Segfault ?

      Posté par  (site web personnel) . Évalué à 2.

      Mets le tout en GPL et tu pourras bénéficier de l'aide de la communauté ! :-)
      C'est deja fait, y'a meme une page sur freshmeat : http://freshmeat.net/projects/pptools/(...)

      Bon, donc voila le code des fonctions liées a inductance::f()

      double inductance::f(void) {
      //this function is a wrapper needed by the solver

      switch(type) {
      case ParalleleWires:
      return parameters[5]-parallele_wires();
      break;
      case CoaxialLine:
      return parameters[5]-coaxial_line();
      break;
      case StripLine:
      return parameters[5]-strip_line();
      break;
      case ConvergingLine:
      return parameters[5]-converging_line();
      break;
      case Disks:
      return parameters[5]-disks();
      break;
      case RectangularCoil:
      return parameters[5]-rectangular_coil();
      break;
      case Helix:
      return parameters[5]-helix();
      break;
      }
      return (double)EXIT_FAILURE;
      }

      et un exemple de fonction appelée:

      double inductance::parallele_wires(void) {
      double length,gap,a,p;

      a=parameters[1];
      gap=parameters[2];
      length=parameters[3];
      p=sqrt(0.25*gap*gap-a*a);
      L=-MU_0/PI*length*(log(gap/a)+log(0.5-p/gap));

      return L;
      }


      Mais le pire, c'est que si je met un printf("Ici\n") au debut de la fonction "f()", rien ne s'affiche (c'est a dire que je n'entre meme pas dans la fonction !). Enfin, oui, je confirme, c'est bien d'un segfault qu'il s'agit...

      Pour ceux qui veulent jetter un oeil au source complet (dans sa version recente avec ce super bug), il est telechargeable (en l'etat) sur http://www.ivanhoe-technologies.com/products/pptools/src/pptools_0.(...)

      Juste une chose, ne pas le mettre sur un FTP publique ou autre, je n'aime pas vraiment faire des releases qui segfault des que l'on clique.... ;-) (eh oui, on a sa fiertée...)

      Ce qui provoque le bug, c'est dans l'onglet "inductance", apres avoir remplit les champs, lorsque l'on clique sur "solve", ça plante immédiatement (mais pas sur mon PPC...)

      Mathias
      • [^] # Suggestion

        Posté par  . Évalué à 1.

        Juste pour voir ce que cela donne : Si ta classe de base equation n'a pas à être instanciée en tant que telle, supprime le code

        double equation::f(void)
        {
        printf("using f(x) from EQUATION class... this is not normal !\n");
        return EXIT_FAILURE;
        }

        et déclare la méthode en tant que méthode virtuelle pure par

        class equation
        {
        ...
        virtual double f(void) = 0;
        ...
        };
      • [^] # Autre suggestion

        Posté par  . Évalué à 1.

        Ecrire un destructeur pour inductance et un constructeur pour equation ...
        • [^] # Re: Autre suggestion

          Posté par  (site web personnel) . Évalué à 1.

          J'ai essayé de declarer f() en tant que methode purement virtuelle dans "equation", pas de changements...
          J'ai aussi essayé d'écrire un destructeur pour inductance et un constructeur pour equation, pas de changements...

          Je me dis que en effet, ce doit etre un problème de pointeur quelque part, qui se promene allegrement dans la mémoire... Hier je ne suis pas parvenu a faire fonctionner valgrind dessus, mais il faut vraiment que j'y arrive, ça pourrait m'aider a trouver ce qui ne va pas...

          On vient aussi de tester sur Solaris/Sparc, meme segfault...

          Mathias
          PS: Merci tout le monde pour vos conseils !!
          • [^] # Re: Autre suggestion

            Posté par  . Évalué à 2.

            Je pense que c'est un effet de bord. Soit la segfault paraît lors de l'appel aux sous-fonctions dans ton switch (gdb + bt roulaizent), soit c'est ton tableau de parameters qui est mal déclaré. En admettant que ta macro MAX_EQ_PARAMETERS ne puisse pas être définie pour une raison ou une autre (ex: oubli du #include idoine), ta déclaration sera alors résolue en

            double parameters[];

            Ce qui reste correct d'un point de vue syntaxique, mais qui définit un pointeur sans la mémoire qui va derrière. Cela suffirait à expliquer tes segfaults intermittentes : Lorsque tu écriras dans ce tableau, tes données n'iront pas se loger dans un endroit prévu à cet effet mais dans l'espace réservé aux variables membres que tu définis plus loin ! Donc, tu as la place de semer la pagaille un bon moment avant de planter. En fait, ton programme pourra continuer à faire le con tant qu'il ne sortira pas du segment de mémoire alloué pour ta classe entière, lequel segment aura probablement une taille alignée sur une page quelquonque. Ceci pourrait expliquer les différences de plantage en fonction des plateformes.
  • # Ou tout autre chose

    Posté par  . Évalué à 2.

    C'est peut-être un bon vieux problème de pointeur ou un écrasement de mémoire qui conduit à un faux diagnostique d'erreur.
  • # Accés à l'extérieur d'un tableau !

    Posté par  . Évalué à 3.

    Salut,
    Le probléme se situe dans le fichier rlcwindow.ui.h
    dans la fonction :

    int RLCwindow::solve_inductance() (ligne 109 )
    tu déclares int index_to_solve[2]
    et dans la suite tu essayes plusieurs fois d'accéder à index_to_solve[2]( lignes 123,128,133( "troisiéme place" d'un tableau de deux éléments ( index_to_solve[0] et index_to_solve[1] )
    • [^] # Re: Accés à l'extérieur d'un tableau !

      Posté par  (site web personnel) . Évalué à 1.

      Effectivement !

      Merci beaucoup pour cette aide précieuse... je me suis fait avoir comme un débutant... Ca m'apprendra a utiliser les tableaux un coup de 0->n puis ensuite brutalement de 1->n....

      Chapeau bas, et merci beaucoup ! Et a bientot pour la prochaine release !

      Mathias
      • [^] # Re: Accés à l'extérieur d'un tableau !

        Posté par  (site web personnel) . Évalué à 2.

        Tu devrais utiliser valgrind. Il t'aurait trouvé ça tout de suite (et justement avant que ça plante, ce qui t'aurait permis de résoudre ton problème en deux secondes).

        Quant à gdb cité par d'autres, tu devrais aussi l'utiliser, mais dans le cas de corruption mémoire comme ton problème, c'est inutile car le programme plantera parfois plusieurs centaines de lignes après l'origine de la corruption mémoire (souvent c'est un plantage dans la glibc d'ailleurs, ce qui est au mieux drôle et au pire rageant).

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.