Bonjour à tous.<br><br>
Voilà, je suis en train de coder une class Noeud pour faire un arbre binaire, seulement, un petit problème apparait.<br>
A la fin de mon programme, je souhaite supprimer l'arbre que je viens de créer, et là, j'ai le droit à ceci : "Erreur de segmentation" :s <br><br>
Voici un peu mon code :<br><br><pre class="brush: cpp;">#include <iostream>
#include <list>
#include "Noeud.h"
using namespace std;
typedef Noeud Arbre;
int main(int argc, char **argv)
{
string expression;
list<Noeud*> pile;
Arbre *arbre = NULL;
Noeud *nouveauNoeud = NULL;
cout << "Entrez une expression postfixée : ";
getline(cin, expression);
for(int i = 0 ; i < expression.size() ; i++)
{
nouveauNoeud = new Noeud(expression[i]);
if((expression[i] == '+') || (expression[i] == '-') || (expression[i] == '*') || (expression[i] == '/'))
{
nouveauNoeud->setFilsDroit(pile.back());
pile.pop_back();
nouveauNoeud->setFilsGauche(pile.back());
pile.pop_back();
}
pile.push_back(nouveauNoeud);
}
arbre = new Noeud(pile.back());
delete nouveauNoeud;
delete arbre;
return 0;
}
</pre><br><br>
Et, je sais que l'erreur se produit lorsque je fais <span class="code2 cpp"><span class="k">delete</span> <span class="n">arbre</span><span class="p">;</span>
</span>.<br><br>
Voici mon destructeur pour Noeud.cpp :<br><br><pre class="brush: cpp;">/* du code avant */
Noeud::~Noeud()
{
if(m_gauche != NULL)
delete m_gauche;
if(m_droit != NULL)
delete m_droit;
}
/* du code après */
</pre><br><br>
Voilà, je ne comprends pas vraiment pourquoi j'ai cette erreur je dois avouer...<br><br>
Si quelqu'un à une piste, je suis preneur !Le 13 octobre 2008 à 20:47:36
Bonjour à tous.
Voilà, je suis en train de coder une class Noeud pour faire un arbre binaire, seulement, un petit problème apparait.
A la fin de mon programme, je souhaite supprimer l'arbre que je viens de créer, et là, j'ai le droit à ceci : "Erreur de segmentation" :s
Il est inutile de tester si un pointeur n'est pas nul avant un delete.<br><br>
Sinon juste avec ça on pourra pas t'aider, fait un code minimal.Le 13 octobre 2008 à 20:56:56
Il est inutile de tester si un pointeur n'est pas nul avant un delete.
Sinon juste avec ça on pourra pas t'aider, fait un code minimal.
- Pourquoi tu fais une déclaration anticipé dans ton header ?<br>
- Utilises la liste d'initialisation au maximum.<br>
- Comme déjà dit, il est inutile de tester si un pointeur n'est pas nul avant un delete.<br>
- J'ai pas trop confiance en tes constructeurs n°2 (réallocation) et n°3 (copie du pointeur).<br>
- les "if(a == b) return true; else return false;" c'est moche, "return a == b;" suffit.<br>
- Je comprends pas ce que tu cherches à faire dans ton main().<br><br>
Corriges ton code en conséquence et commentes (ou expliques) mieux ce que tu veux faire, Courage.Le 13 octobre 2008 à 21:18:36
- Pourquoi tu fais une déclaration anticipé dans ton header ?
- Utilises la liste d'initialisation au maximum.
- Comme déjà dit, il est inutile de tester si un pointeur n'est pas nul avant un delete.
- J'ai pas trop confiance en tes constructeurs n°2 (réallocation) et n°3 (copie du pointeur).
- les "if(a == b) return true; else return false;" c'est moche, "return a == b;" suffit.
- Je comprends pas ce que tu cherches à faire dans ton main().
Corriges ton code en conséquence et commentes (ou expliques) mieux ce que tu veux faire, Courage.
anonyme
<p><strong>Citation : Chlab_lak</strong></p><blockquote>- Pourquoi tu fais une déclaration anticipé dans ton header ?</blockquote><br><br>
J'ai toujours cru que lorsqu'on utilisait un objet dans l'objet lui-même, il fallait faire une déclaration anticipée. Force est de constater que non.<br><br><br><p><strong>Citation : Chlab_lak</strong></p><blockquote>- Utilises la liste d'initialisation au maximum.</blockquote><br><br>
c'est-à-dire ? Liste d'initialisation ?<br><br><p><strong>Citation : Chlab_lak</strong></p><blockquote>- Comme déjà dit, il est inutile de tester si un pointeur n'est pas nul avant un delete.</blockquote><br>
Corrigé.<br><br><p><strong>Citation : Chlab_lak</strong></p><blockquote>- J'ai pas trop confiance en tes constructeurs n°2 (réallocation) et n°3 (copie du pointeur).</blockquote><br><br>
Modifié. (Mieux ?)<br><br><br><p><strong>Citation : Chlab_lak</strong></p><blockquote>- les "if(a == b) return true; else return false;" c'est moche, "return a == b;" suffit.</blockquote><br>
Corrigé.<br><br><p><strong>Citation : Chlab_lak</strong></p><blockquote>- Je comprends pas ce que tu cherches à faire dans ton main().</blockquote><br>
Alors en fait, je voudrais construire un arbre binaire selon une expression postfixée. Par exemple, l'expression mathématique "A + B" en écriture postfixée donne "AB+", et c'est par rapport à cette expression que je construis mon arbre. Ainsi, si je tombe sur un signe mathématique, j'ajoute les deux derniers éléments de la pile à l'arbre, sinon, je met l'élément dans la pile, en attendant de tomber sur un signe...<br><br>
Voici mes modifications :<br><br><pre class="brush: cpp;">#include <iostream>
#include <list>
#include "Noeud.h"
using namespace std;
typedef Noeud Arbre;
int main(int argc, char **argv)
{
string expression;
list<Noeud*> pile;
Arbre *arbre = NULL;
Noeud *nouveauNoeud = NULL;
cout << "Entrez une expression postfixée : ";
getline(cin, expression);
for(int i = 0 ; i < expression.size() ; i++)
{
nouveauNoeud = new Noeud(expression[i]);
if((expression[i] == '+') || (expression[i] == '-') || (expression[i] == '*') || (expression[i] == '/'))
{
nouveauNoeud->setFilsDroit(pile.back());
pile.pop_back();
nouveauNoeud->setFilsGauche(pile.back());
pile.pop_back();
}
pile.push_back(nouveauNoeud);
}
arbre = new Noeud(*pile.back());
delete nouveauNoeud;
//delete arbre;
return 0;
}
</pre> <br><br><pre class="brush: cpp;">#ifndef DEF_NOEUD
#define DEF_NOEUD
#include <iostream>
class Noeud
{
public :
Noeud(const char donnees);
Noeud(const Noeud &gauche, const Noeud &droit, const char donnees);
Noeud(const Noeud &noeud);
~Noeud();
char getDonnees();
Noeud* getFilsGauche();
Noeud* getFilsDroit();
void setFilsGauche(Noeud *gauche);
void setFilsDroit(Noeud *droit);
bool possedeFils();
bool filsGauche();
bool filsDroit();
private :
Noeud *m_gauche;
Noeud *m_droit;
char m_donnees; //Contient la données (nombre, caractère...);
};
#endif
</pre><br><br><pre class="brush: cpp;">#include <iostream>
#include "Noeud.h"
Noeud::Noeud(const char donnees)
{
m_donnees = donnees;
m_droit = NULL;
m_gauche = NULL;
}
Noeud::Noeud(const Noeud &gauche, const Noeud &droit, const char donnees)
{
m_donnees = donnees;
m_droit = new Noeud(droit);
m_gauche = new Noeud(gauche);
}
Noeud::Noeud(const Noeud &noeud)
{
m_donnees = noeud.m_donnees;
m_droit = new Noeud(*(noeud.m_droit));
m_gauche = new Noeud(*(noeud.m_gauche));
}
Noeud::~Noeud()
{
delete m_gauche;
delete m_droit;
}
void Noeud::setFilsGauche(Noeud *gauche)
{
m_gauche = gauche;
}
void Noeud::setFilsDroit(Noeud *droit)
{
m_droit = droit;
}
char Noeud::getDonnees() { return m_donnees; }
Noeud* Noeud::getFilsGauche() { return m_gauche; }
Noeud* Noeud::getFilsDroit() { return m_droit; }
bool Noeud::possedeFils() { return filsGauche() || filsDroit(); }
bool Noeud::filsGauche()
{
if(m_gauche != NULL)
return true;
else
return false;
}
bool Noeud::filsDroit()
{
if(m_droit != NULL)
return true;
else
return false;
}
</pre><br><br><br>
Le problème initial est toujours là, soit dit en passant...Le 13 octobre 2008 à 22:23:56
Citation : Chlab_lak
- Pourquoi tu fais une déclaration anticipé dans ton header ?
J'ai toujours cru que lorsqu'on utilisait un objet dans l'objet lui-même, il fallait faire une déclaration anticipée. Force est de constater que non.
Citation : Chlab_lak
- Utilises la liste d'initialisation au maximum.
c'est-à-dire ? Liste d'initialisation ?
Citation : Chlab_lak
- Comme déjà dit, il est inutile de tester si un pointeur n'est pas nul avant un delete.
Corrigé.
Citation : Chlab_lak
- J'ai pas trop confiance en tes constructeurs n°2 (réallocation) et n°3 (copie du pointeur).
Modifié. (Mieux ?)
Citation : Chlab_lak
- les "if(a == b) return true; else return false;" c'est moche, "return a == b;" suffit.
Corrigé.
Citation : Chlab_lak
- Je comprends pas ce que tu cherches à faire dans ton main().
Alors en fait, je voudrais construire un arbre binaire selon une expression postfixée. Par exemple, l'expression mathématique "A + B" en écriture postfixée donne "AB+", et c'est par rapport à cette expression que je construis mon arbre. Ainsi, si je tombe sur un signe mathématique, j'ajoute les deux derniers éléments de la pile à l'arbre, sinon, je met l'élément dans la pile, en attendant de tomber sur un signe...
<p><strong>Citation : TuxWeb</strong></p><blockquote>
<p><strong>Citation : Chlab_lak</strong></p>
<blockquote>- Utilises la liste d'initialisation au maximum.</blockquote>
<br><br>
c'est-à-dire ? Liste d'initialisation ?</blockquote><br><br>
Par exemple pour ton premier constructeur:<br><pre class="brush: cpp;">Node::Node(char Value)
: myValue(Value)
, myLeft(0) // ou NULL si tu préfères
, myRight(0)
{}
</pre><br><br><p><strong>Citation : TuxWeb</strong></p><blockquote>
<p><strong>Citation : Chlab_lak</strong></p>
<blockquote>- J'ai pas trop confiance en tes constructeurs n°2 (réallocation) et n°3 (copie du pointeur).</blockquote>
<br><br>
Modifié. (Mieux ?)</blockquote><br>
Il me semble que c'est mieux, j'ai pas chercher trop loin, mais on peut faire surement mieux. <br><br><p><strong>Citation : TuxWeb</strong></p><blockquote>
<p><strong>Citation : Chlab_lak</strong></p>
<blockquote>- les "if(a == b) return true; else return false;" c'est moche, "return a == b;" suffit.</blockquote>
<br><br>
Corrigé.</blockquote><br>
Tu n'as pas tout corrigé.<br><br><p><strong>Citation : TuxWeb</strong></p><blockquote>Ainsi, si je tombe sur un signe mathématique, j'ajoute les deux derniers éléments de la pile à l'arbre</blockquote><br>
Si tu as A+B:<br>
1) Tu rajoutes A à la liste <br>
2) Il y a une opération => Tu assignes au noeud droit A puis tu l'enlèves de la liste => Ensuite tu refais appelles à back() alors qu'il n'y a plus rien dans la liste => Boum<br><br><p><strong>Citation : TuxWeb</strong></p><blockquote>
<strong>sinon</strong>, je met l'élément dans la pile, en attendant de tomber sur un signe...</blockquote><br>
Je vois pas vraiment où se trouve ton <strong>sinon<br></strong> (else) <img src="/bundles/tinymce/vendor/tiny_mce/plugins/emotions/img/clin.png" alt=";)" class="smilies"><br><br><br>
Je pense pas que tout soit corrigé, mais je te conseille de reprendre ta conception depuis le début car je trouve ton code trop obscure/mal organisé (c'est sans doute pas les meilleures mots mais là je sèche).Le 13 octobre 2008 à 23:15:57
Citation : TuxWeb
Citation : Chlab_lak
- Utilises la liste d'initialisation au maximum.
c'est-à-dire ? Liste d'initialisation ?
Par exemple pour ton premier constructeur:
Node::Node(char Value)
: myValue(Value)
, myLeft(0) // ou NULL si tu préfères
, myRight(0)
{}
Citation : TuxWeb
Citation : Chlab_lak
- J'ai pas trop confiance en tes constructeurs n°2 (réallocation) et n°3 (copie du pointeur).
Modifié. (Mieux ?)
Il me semble que c'est mieux, j'ai pas chercher trop loin, mais on peut faire surement mieux.
Citation : TuxWeb
Citation : Chlab_lak
- les "if(a == b) return true; else return false;" c'est moche, "return a == b;" suffit.
Corrigé.
Tu n'as pas tout corrigé.
Citation : TuxWeb
Ainsi, si je tombe sur un signe mathématique, j'ajoute les deux derniers éléments de la pile à l'arbre
Si tu as A+B:
1) Tu rajoutes A à la liste
2) Il y a une opération => Tu assignes au noeud droit A puis tu l'enlèves de la liste => Ensuite tu refais appelles à back() alors qu'il n'y a plus rien dans la liste => Boum
Citation : TuxWeb
sinon, je met l'élément dans la pile, en attendant de tomber sur un signe...
Je vois pas vraiment où se trouve ton sinon (else)
Je pense pas que tout soit corrigé, mais je te conseille de reprendre ta conception depuis le début car je trouve ton code trop obscure/mal organisé (c'est sans doute pas les meilleures mots mais là je sèche).
<citation rid="3049817<p><strong>Citation : TuxWeb</strong></p><blockquote>
<p><strong>Citation : Chlab_lak</strong></p>
<blockquote>- J'ai pas trop confiance en tes constructeurs n°2 (réallocation) et n°3 (copie du pointeur).</blockquote>
<br><br>
Modifié. (Mieux ?)</blockquote><br>
Il me semble que c'est mieux, j'ai pas chercher trop loin, mais on peut faire surement mieux. </citation><br><br>
Je pose plutot la question: Ces constructeurs ont-ils un sens ? <br><br>
Sinon, tu peux essayer le debuggueur pour repérer ou se situe l'erreur.StaffLe 14 octobre 2008 à 14:10:10
<citation rid="3049817
Citation : TuxWeb
Citation : Chlab_lak
- J'ai pas trop confiance en tes constructeurs n°2 (réallocation) et n°3 (copie du pointeur).
Modifié. (Mieux ?)
Il me semble que c'est mieux, j'ai pas chercher trop loin, mais on peut faire surement mieux. </citation>
Je pose plutot la question: Ces constructeurs ont-ils un sens ?
Sinon, tu peux essayer le debuggueur pour repérer ou se situe l'erreur.
<p><strong>Citation : Nanoc</strong></p><blockquote>
<br>
Je pose plutot la question: Ces constructeurs ont-ils un sens ? <br>
</blockquote><br><br>
Il est vrai que le 2ième constructeur n'est pas utile, (mais je m'en étais servi avant). Néanmoins, pour le troisième, il trouve son sens dans le fait que j'en ai besoin pour recopier la qui est dans la pile sur mon arbre "final", non ? Dois-je procéder autrement ?<br><br><p><strong>Citation : Nanoc</strong></p><blockquote>
<br>
Sinon, tu peux essayer le debuggueur pour repérer ou se situe l'erreur. <br>
</blockquote><br><br><span class="barre">Je sais que l'erreur se trouve dans le destructeur de Noeud. Mais pas plus <img src="/bundles/tinymce/vendor/tiny_mce/plugins/emotions/img/triste.png" alt=":(" class="smilies"></span>. Je vais voir ce que je peux avoir avec un débuggeur.<br><br><br><p><strong>Citation : Chlab_lak</strong></p><blockquote>
<br><p><strong>Citation : TuxWeb</strong></p>
<blockquote>
<br>
sinon, je met l'élément dans la pile, en attendant de tomber sur un signe...</blockquote>
<br><br>
Je vois pas vraiment où se trouve ton sinon<br>
(else) <img src="/bundles/tinymce/vendor/tiny_mce/plugins/emotions/img/clin.png" alt=";)" class="smilies"><br>
</blockquote><br><br>
En fait, il n'y a pas de "sinon", il faut toujours ajouter l'élément dans la pile.<br><br><p><strong>Citation : Chlab_lak</strong></p><blockquote>
<br>
Si tu as A+B:<br>
1) Tu rajoutes A à la liste<br>
2) Il y a une opération => Tu assignes au noeud droit A puis tu l'enlèves de la liste => Ensuite tu refais appelles à back() alors qu'il n'y a plus rien dans la liste => Boum<br>
</blockquote><br><br>
D'où l'interêt d'utiliser l'expression postfixée de A+B (à savoir AB+)<br><br><br>
Edit : Je vous donne les informations au fur et à mesure que je les obtiens.<br><br>
Alors mon débuggeur me dit ceci : <br><br><pre class="brush: plain;">Starting program: /home/tuxweb/Programmation/C++/Console/Algo/Chap5/Expression_algo/exe
Entrez une expression postfixée : AB+
Program received signal SIGSEGV, Segmentation fault.
0x08049309 in Noeud (this=0x9957098, noeud=@0x0) at Noeud.cpp:20
20 m_donnees = noeud.m_donnees;
Current language: auto; currently c++
(gdb)</pre><br><br>
Je ne comprends pas pourquoi ça plante ici je dois dire... :s<br><br>
Edit2 : Après tests, il s'avèrerait que c'est tout le constructeur de copie qui fait planter :s<br><br>
Edit3 : C'est bon, ça fonctionne !<br><br>
J'ai modifié mon constructeur de copie comme ceci : <br><pre class="brush: cpp;">Noeud::Noeud(const Noeud &noeud)
{
m_donnees = noeud.m_donnees;
if(noeud.filsGauche())
m_gauche = new Noeud(*(noeud.m_gauche));
else
m_gauche = NULL;
if(noeud.filsDroit())
m_droit = new Noeud(*(noeud.m_droit));
else
m_droit = NULL;
}
</pre><br><br>
J'ai compris ce qu'il se passait réellement grâce au debuggeur. Je ne m'en étais jamais servi auparavant. Je dois avouer que c'est plutôt pratique et efficace !<br><br>
Merci !Le 14 octobre 2008 à 18:11:20
Citation : Nanoc
Je pose plutot la question: Ces constructeurs ont-ils un sens ?
Il est vrai que le 2ième constructeur n'est pas utile, (mais je m'en étais servi avant). Néanmoins, pour le troisième, il trouve son sens dans le fait que j'en ai besoin pour recopier la qui est dans la pile sur mon arbre "final", non ? Dois-je procéder autrement ?
Citation : Nanoc
Sinon, tu peux essayer le debuggueur pour repérer ou se situe l'erreur.
Je sais que l'erreur se trouve dans le destructeur de Noeud. Mais pas plus . Je vais voir ce que je peux avoir avec un débuggeur.
Citation : Chlab_lak
Citation : TuxWeb
sinon, je met l'élément dans la pile, en attendant de tomber sur un signe...
Je vois pas vraiment où se trouve ton sinon
(else)
En fait, il n'y a pas de "sinon", il faut toujours ajouter l'élément dans la pile.
Citation : Chlab_lak
Si tu as A+B:
1) Tu rajoutes A à la liste
2) Il y a une opération => Tu assignes au noeud droit A puis tu l'enlèves de la liste => Ensuite tu refais appelles à back() alors qu'il n'y a plus rien dans la liste => Boum
D'où l'interêt d'utiliser l'expression postfixée de A+B (à savoir AB+)
Edit : Je vous donne les informations au fur et à mesure que je les obtiens.
Alors mon débuggeur me dit ceci :
Starting program: /home/tuxweb/Programmation/C++/Console/Algo/Chap5/Expression_algo/exe
Entrez une expression postfixée : AB+
Program received signal SIGSEGV, Segmentation fault.
0x08049309 in Noeud (this=0x9957098, noeud=@0x0) at Noeud.cpp:20
20 m_donnees = noeud.m_donnees;
Current language: auto; currently c++
(gdb)
Je ne comprends pas pourquoi ça plante ici je dois dire... :s
Edit2 : Après tests, il s'avèrerait que c'est tout le constructeur de copie qui fait planter :s
Edit3 : C'est bon, ça fonctionne !
J'ai modifié mon constructeur de copie comme ceci :
J'ai compris ce qu'il se passait réellement grâce au debuggeur. Je ne m'en étais jamais servi auparavant. Je dois avouer que c'est plutôt pratique et efficace !
Merci !
Arbre binaire (Destruction d'un noeud)
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.