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 :

Segmentation fault sur destruction d'une structure


Sujet :

C++

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    348
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 348
    Points : 103
    Points
    103
    Par défaut Segmentation fault sur destruction d'une structure
    Bonjour a tous,

    D'abord je voudrais m'excuser pour le "flood" de topics en ce moment, vu que j'en suis a mon quatrieme pour un meme projet. J'essaie autant que possible de limiter le nombre de questions, et c'est seulement quand je seche au bout de plusieurs heures et que je n'ai aucune autre alternative que j'en poste un, dans l'espoir qu'il soit aussi constructif aux autres.

    Pour en revenir a mon probleme, le voici :

    Polynome.cxx (uniquement les fonctions qui nous interessent ici)
    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
    string Polynome::AffichePolynome ()
    {
    	if (Coefficients!=NULL)
    	{
    		cout<<Coefficients[0];
    		for (int i=1; i<Degre; i++)
    		{
    			if (Coefficients[i]<0)
    			{
    				cout<<"-";
    			}		
    			else
    			{
    				if (Coefficients[i]!=0)
    				{
    					cout<<"+"<<Coefficients[i]<<"*x";
    					if (i>1)
    					{
    						cout<<"^"<<i;
    					}
    				}
    			}
    		}
    	}
    	else
    	{
    		cout<<"POLYNOME_NUL";
    	}
    }
     
    Polynome::~Polynome()
    {
    	if (Coefficients!=NULL)
    	{
    		delete[] Coefficients;
    		Coefficients=NULL;
    	}
    }
    Polynome.hxx (tout le fichier)
    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
    #include "RacineFonctions.hxx"
    #include <string>
     
    using namespace std;
     
    #ifndef POLYNOME
    #define POLYNOME
     
    class Polynome : public RacineFonctions
    {
    	private:
    	int Degre;
    	double* Coefficients;
     
    	public:
    	Polynome(int=0, double* = NULL);
    	Polynome(const Polynome&);
    	~Polynome(void);
    	double Evalue(int, double) ;
    	Intervalle Evalue(int, const Intervalle&);
    	string AffichePolynome(void);
     
    	Polynome operator = (const Polynome&);
    };
    #endif
    Main.cxx (tout le fichier)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    #include "Polynome.hxx"
     
    int main ()
    {
    	double a[3] = {2.,-3.,1.};
    	Polynome P1(2,a);
    	P1.AffichePolynome();
    	return 0;
    }
    Resultat :

    Le compilateur me signale un Segmentation Fault.
    Il n'a pas lieu si j'enleve P1.AffichePolynome(); du main.
    Si je laisse le runtime utiliser le destructeur par defaut en mettant le mien en commentaire avec son prototype, j'ai un glibc detected suivi d'un tas de lignes incomprehensibles (qui correspondrait apparemment a un free() sur une variable non "malloquee").

    Je sais que mon code presente quelques autres imperfections, mais je ne leur donne pas la priorite pour le moment. Merci de votre aide.

    Edit : Le debogueur "DDD" arrive bien, dans la fonction AffichePolynome(), au "else" si je cree un Polynome sans parametres (donc il prend en fait les parametres par defaut), et au "if" si je cree un Polynome avec 2 et a en parametre. Dans les deux cas, il recoit un SIGVSEGFAULT juste apres l'execution de AffichePolynome(). C'est pour ca que je bloque, bien que cet outil m'ait pas mal depanne dans le passe.

  2. #2
    r0d
    r0d est déconnecté
    Expert éminent

    Homme Profil pro
    tech lead c++ linux
    Inscrit en
    Août 2004
    Messages
    4 262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : tech lead c++ linux

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

    je ne sais pas où est l'erreur. A mon avis, elle est ailleurs. Peut-être lors de la construction. Il faudrait que tu nous montre le code des constructeurs.
    En attendant, quelques remarques:
    Citation Envoyé par User Name Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    	Polynome operator = (const Polynome&);
    Cet operateur n'est pas bon. Ce n'est pas impossible que le problème vienne de là d'ailleurs.
    Tel qu'il est définit ici, ton opérateur d'affectation renvoie une copie de Polynome, or il devrait renvoyer une référence sur lui-même:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Polynome & operator = (const Polynome& source)
    {
       // code
       return *this;
    }
    Citation Envoyé par User Name Voir le message
    Si je laisse le runtime utiliser le destructeur par defaut en mettant le mien en commentaire avec son prototype, j'ai un glibc detected suivi d'un tas de lignes incomprehensibles
    C'est normal: tu as un pointeur parmi tes variables membres (Coefficients), ce qui signifie de la mémoire dynamique, ce qui signifie que c'est à toi de gérer cette mémoire. C'est donc à toi de gérer la construction et la destruction. Ta classe est bien définie (il y a tout ce qui faut: default ctor, copy ctor, assign ctor, et dtor), à l'erreur sur l'op. d'assignation près; reste à voir son implémentation.

    D'où, pour une nième fois (n tendant vers l'infini), le conseil d'utiliser un std::vector plutôt qu'un tableau c-style (dynamique de surcroît).
    « L'effort par lequel toute chose tend à persévérer dans son être n'est rien de plus que l'essence actuelle de cette chose. »
    Spinoza — Éthique III, Proposition VII

  3. #3
    Membre émérite

    Inscrit en
    Mai 2008
    Messages
    1 014
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 1 014
    Points : 2 252
    Points
    2 252
    Par défaut
    Hmmm, rassure-moi User Name, ton constructeur fait bien une copie du tableau passé en paramètre ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    Polynome(int i, double* d)
    {
       Degre = i;
       Coefficients = new double[i];
       std::copy(d, d+ i,  Coefficients );
    };
    Parce que si tu copies directement le pointeur comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Polynome(int i, double* d)
    {
       Degre i;
       Coefficients = d;
    };
    Alors clairement le code suivant est faux :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    #include "Polynome.hxx"
     
    int main ()
    {
       double a[3] = {2.,-3.,1.};
       Polynome P1(2,a);
    }
    Car alors le destructeur de Polynome tente de faire un delete[] sur "a", tableau qui n'a pas été alloué par new[] et qui se trouve probablement sur la pile !!

    (Et comme rod je préconise std::vector pour éviter ce genre de problème, le code du constructeur deviendrait alors :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Polynome(int i, double* d):
    Coefficients(d, d+ i)
    {
       // pas besoin de Degre... car == à Coefficients.size()
    };
    )

  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
    Points : 13 017
    Points
    13 017
    Par défaut
    Salut,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    string Polynome::AffichePolynome ()
    Cette fonction ne retourne rien, ce qui revient à dire côté appelant que le destructeur de std::string est appelé sur une chaîne non initialisée => boum.

    Sinon, +1000 avec Arzar et r0d pour troquer tes pointeurs avec un joli std::vector

  5. #5
    Membre émérite

    Inscrit en
    Mai 2008
    Messages
    1 014
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 1 014
    Points : 2 252
    Points
    2 252
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    Salut,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    string Polynome::AffichePolynome ()
    Cette fonction ne retourne rien
    Mais c'est vrai ça ! Comment est-ce que ce code peut compiler en premier lieu ? C'est louche cette histoire.

  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
    Points : 13 017
    Points
    13 017
    Par défaut
    Citation Envoyé par Arzar Voir le message
    Mais c'est vrai ça ! Comment est-ce que ce code peut compiler en premier lieu ? C'est louche cette histoire.
    Un vieux reste de (très) vieux C probablement. Ca compile en mingw (même avec une ribambelle de -W et -std=c++98 et -ansi) avec quand même un petit warning. En revanche, Visual refuse de le compiler avec des options par défaut.

  7. #7
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    348
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 348
    Points : 103
    Points
    103
    Par défaut
    Merci pour vos conseils. Je precise que je ne peux pas utiliser de std::Vector, car c'est mon professeur qui m'impose l'utilisation d'un double*. Ne me demandez pas pourquoi, je n'en sais rien (peut-etre parce qu'on n'a jamais entendu parler en cours de Vector en C++, meme si notre curiosite suffit a nous l'apprendre).

    Pour le reste, je m'y atele et je vous tiens au courant.

  8. #8
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    348
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 348
    Points : 103
    Points
    103
    Par défaut
    Effectivement, c'etait a cause du bete string a la place du void en retour dans ma fonction PolynomeAffiche() ! J'aurais pu chercher encore longtemps !

    Par contre, et ca me scandalise profondement, je ne peux pas faire de return (*this) dans mon operator = : le compilateur m'afficherait cette erreur.

  9. #9
    Expert éminent sénior

    Avatar de dragonjoker59
    Homme Profil pro
    Software Developer
    Inscrit en
    Juin 2005
    Messages
    2 031
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Software Developer
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 2 031
    Points : 11 477
    Points
    11 477
    Billets dans le blog
    11
    Par défaut
    Et pourtant tu DOIS faire return *this dans ton operateur d'affectation. L'erreur que tu pointes n'a à priori aucun rapport.
    Si vous ne trouvez plus rien, cherchez autre chose...

    Vous trouverez ici des tutoriels OpenGL moderne.
    Mon moteur 3D: Castor 3D, presque utilisable (venez participer, il y a de la place)!
    Un projet qui ne sert à rien, mais qu'il est joli (des fois) : ProceduralGenerator (Génération procédurale d'images, et post-processing).

  10. #10
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    348
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 348
    Points : 103
    Points
    103
    Par défaut
    Tu as raison pour le return (*this). Les deux problèmes sont résolus. Merci à tous, aussi efficaces que d'habitude !

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

Discussions similaires

  1. Réponses: 9
    Dernier message: 24/01/2008, 12h53
  2. destruction d'une structure
    Par salseropom dans le forum C
    Réponses: 10
    Dernier message: 07/11/2006, 12h04
  3. Segmentation fault sur new[] et delete[]
    Par Don ViP dans le forum C++
    Réponses: 4
    Dernier message: 30/04/2006, 00h29
  4. Segmentation Fault sur un fclose
    Par Beush dans le forum C
    Réponses: 9
    Dernier message: 30/11/2005, 19h30
  5. Segmentation fault sur un gethostbyname ?
    Par Mitox dans le forum Réseau
    Réponses: 9
    Dernier message: 25/11/2005, 16h17

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