Erreur de segmentation (segfault) dans une fonction vide

Résolu
cs_tiouil Messages postés 51 Date d'inscription dimanche 8 août 2010 Statut Membre Dernière intervention 2 mars 2018 - 17 avril 2011 à 20:45
cs_tiouil Messages postés 51 Date d'inscription dimanche 8 août 2010 Statut Membre Dernière intervention 2 mars 2018 - 19 avril 2011 à 13:37
Bonjour, j'ai une erreur de segmentation lorsque je fait appel a une fonction vide () via un pointeur. Si quelqu'un peut m'aider ^^.

Pour le contexte, je suis au debut d'un logiciel qui va avoir acces à une base de données sous linux.
J'utilise une architecture modele/vue (pas de controleur).
Je ne vous met pas le code de la vue car cela ne sert pas. Elle sert juste d'interface utilisateur et change le modele via les accesseur (type de la personne, choix...).

Le debuggeur gdb m'affiche une erreur a l'appel de secretaire ou responsable sur le menu1 car pour l'instant a part lui et le menu general il n'y a pas grand chose (depend du choix de l'utilisateur)

//ArchiModele.cc
#include "ArchiModel.h"
#include "Personne.h"
#include "Secretaire.h"
#include "Responsable.h"
#include <string.h>
#include 
#include <cstdlib>

using namespace std;

/****************************************
 			Constructeur
****************************************/
ArchiModel::ArchiModel() : _w(800), _h(600)
{
_type = ttlm;
_count_delete = 0;
_menu = mg;
_choix = rien;
_responsable = new Responsable();
_secretaire = new Secretaire();
}

ArchiModel::ArchiModel(int w, int h) :  _w(w), _h(h)
{

}

/****************************************
 			Destructeur
****************************************/

ArchiModel::~ArchiModel()
{
if(_count_delete < 1) //le modele fait appel au destr de resp et secre, si on ne met pas cela, quand archiVue fait delete _model, il on le refait -> erreur
{
if(_responsable != NULL)
delete _responsable;
if(_secretaire != NULL)
delete _secretaire;
_count_delete++;	
}
}

/****************************************
 		Accesseurs en lecture
****************************************/

string ArchiModel::getType()
{
switch (_type) // "break" n'est pas utile car return stop la fonction
{
case ttlm :
{
return "ttlm";
}
case responsable :
{
return "responsable";
}
case secretaire :
{
return "secretaire";
}
default :
{
abort(); //on quitte il y a une erreur
}
}
}

string ArchiModel::getIdMenu()
{
switch (_menu) // "break" n'est pas utile car return stop la fonction
{
case mg :
{
return "menu_general";
}
case m1 :
{
return "menu_1";
}
case m2:
{
return "menu_2";
}
default :
{
return "menu_general"; //On revient au menu general car erreur
}
}
}


/****************************************
 		Accesseurs en ecriture
****************************************/

void ArchiModel::setChoix(string choix)
{
if(_menu == mg)
{
if(choix == "choix_1")
{
_type = responsable;
}
else
_type = secretaire;
}
else if(choix == "choix_2")
_choix = c2;
else if(choix == "choix_3")
_choix = c3;
else if(choix == "choix_4")
_choix = c4;
}

/*void ArchiModel::setType(string pers)
{
if(pers == "secretaire")
_type = secretaire;
else if(pers == "responsable")
_type = responsable;
else 
_type = ttlm;
}*/

void ArchiModel::setIdMenu(string que_fait_on)
{
switch (_menu) // "break" n'est pas utile car return stop la fonction
{
case mg :
{
if(que_fait_on == "+")
_menu = m1;
break;
}
case m1 :
{
if(que_fait_on == "+") //confirmer -> on va au menu suivant
_menu = m2;
if(que_fait_on == "-") //retour -> on va au menu precedent
_menu = mg;
else //menu -> on retourne au menu general
_menu = mg;
break;
}
case m2:
{
/*if(que_fait_on == "+") //Plus de menu suivant on fait l'action demande DANS UNE NOUVELLE FENETRE
_menu = m3;*/
if(que_fait_on == "-")
_menu = m1;
else
_menu = mg;
break;
}
default :
{
_menu = mg; //On revient au menu general car erreur
break;
}
}
}

/****************************************
 			Prochaine etape
****************************************/
void ArchiModel::nextStep()
{
switch (_type)
{
case responsable :
{
if(_menu == m1)
{
_responsable->menu1();//Erreur de seg
}
else if(_menu == m2)
{
_responsable->menu2();
}
break;
}
case secretaire :
{
if(_menu == m1)
{
_secretaire->menu1(); //Erreur de seg
}
else if(_menu == m2)
{
_secretaire->menu2();
}
break;
}
default : //ttlm
{
_menu = mg;
break;
}
}
}


//Personne.cc
#include "Personne.h"

using namespace std;

/****************************************
Constructeur
****************************************/

Personne::Personne()
{	

}

/****************************************
Destructeur
****************************************/  

Personne::~Personne()
{

}


//Personne.h

#ifndef _PERSONNE_
#define _PERSONNE_

class Personne{  
 public:

  Personne();
  virtual ~Personne();

  virtual void menu1() = 0; //methode abstraite
  virtual void menu2() = 0; // idem
};
#endif


//Secretaire.cc
#include "Secretaire.h"
#include 
#include <cstdlib>

using namespace std;

/****************************************
Constructeur
****************************************/

Secretaire::Secretaire()
{	

}

/****************************************
       Destructeur
****************************************/  

Secretaire::~Secretaire()
{

}

/****************************************
 Menus de la secretaire
****************************************/

void Secretaire::menu1()
{
cout<<"menu1 secr"<<endl;
}

void Secretaire::menu2()
{
cout<<"menu1 secr"<<endl;
}


//Secretaire.h

#ifndef _SECRETAIRE_
#define _SECRETAIRE_

#include "Personne.h"

class Secretaire : public Personne
{  
 public:

  Secretaire();
  ~Secretaire();

  virtual void menu1();
  virtual void menu2();
    
};
#endif


ps : secretaire et responsable sot identiques pour le moment donc je ne vous met que secretaire.

Merci par avance pour votre patience.
Cyril Z.

16 réponses

fregolo52 Messages postés 1114 Date d'inscription mercredi 15 juin 2011 Statut Membre Dernière intervention 6 mai 2021 4
18 avril 2011 à 08:32
Je ne sais un grand pro du C++, mais :
Personne a des méthodes virtuelles pures, ok !
virtual void menu1() = 0; //methode abstraite

Seccretaire doit l'implémenter :
void menu1();
3
cs_tiouil Messages postés 51 Date d'inscription dimanche 8 août 2010 Statut Membre Dernière intervention 2 mars 2018
18 avril 2011 à 11:10
Bonjour, je sais mais justement j'ai ajouté un cout<<, donc meme si je travail avec la sfml, comme j'ouvre mon terminal pour lancé ma .exe, il devrait me l'affichait or il n'affiche meme pas le cout<<. J'en conclu donc que c'est au moment de l'appel comme le debuggeur mais pourquoi.

Je me sers du polymorphisme et je respecte les regles, methode abstraire = redefinition de classe fille avec meme prototype -> c'est OK, appel avec un pointeur donc il differencie bien les deux classes (secretaire, responsable).

HELP!!!!!!

Si tu as une autre idée n'hesites pas, merci


Cyril Z.
0
cs_tiouil Messages postés 51 Date d'inscription dimanche 8 août 2010 Statut Membre Dernière intervention 2 mars 2018
18 avril 2011 à 11:12
J'ai oublié de te dire qu'en enlevant virtual de secretaire et de responsable ca marche toujours pas. (D'ailleur j'ai d'abord essayer cette solution mais en me balladant sur les forums j'ai trouvé ca)


Cyril Z.
0
cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 123
18 avril 2011 à 19:10
Poste un exemple complet qui compile, et je te le débuggerais/améliorerais :)
(J'ai abandonné en essayant de refaire ton "ArchiModele.h", un peu chiant à faire).

Premières remarques:
- Évite les "using namespace", voir: http://0217021.free.fr/portfolio/axel.berardino/articles/bon-usage-using-namespace
- N'utilise pas NULL, voir: http://0217021.free.fr/portfolio/axel.berardino/articles/null-en-cpp
- Inutile de vérifier si un pointeur est null avant de faire un "delete". Delete vérifie déjà cela, et ne fais rien. Ex: delete 0, est tout à fait valide et ne fait rien.
- Avoir de l'héritage et faire ensuite un switch case... Y a un gros problème de conception.
- Des strings et des chars à la place des enums ? Oo
- Nomme tes headers .hh, .h c'est pour le C. (Généralement on a l'un des couples suivants: .hh/.cc, .hpp/.cpp).

________________________________________________________________________
Historique de mes créations, et quelques articles:
[ http://0217021.free.fr/portfolio http://0217021.free.fr/portfolio]
Merci d'utiliser Réponse acceptée si un post répond à votre question
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
cs_tiouil Messages postés 51 Date d'inscription dimanche 8 août 2010 Statut Membre Dernière intervention 2 mars 2018
18 avril 2011 à 20:25
Bonjour, je suis etudiant en info et nos profs nous on appris certaines choses et l'utilisent eux memes (se sont des enseignants chercheurs au labri donc je ne me fait pas de soucis ^^) :
- pour les usings cela vient d'eux et dans une autoformation il l'on utilisé (debut de notre code pour le sujet)
- pour la verificaétion des deletes c'est pareil c'est "leur code" que j'ai adapté.
- de meme pour le nom des fichiers pour nous et pour eux (meme lors TD et TP) c'est .cc et .h, autrement dit il ne veulent sans doute pas que l'on utilise .hh

Sinon, qu'entends tu par chars et string a la place des enums ? et par switch case dans l'heritage ?

Et encore, j'ai resolu l'erreur de seg en faisant sauter la classe personne et en renommant differemment le nom des fonctions de secretare et responsable car apres tout elles n'auront pas de fonction en commum etant donnée que je vais leur donnée un nom suivant leur action (ajout BD, suppr, test.....). -> mise a part peut-etre une en commun mais bon ..... je m'arrangerais.

Pour finir as tu un bon cours sur le polymorphisme car l'erreur venait de la, meme si cela n'est pas la bonne reponse :

[quote]
Je ne sais un grand pro du C++, mais :
Personne a des méthodes virtuelles pures, ok !
virtual void menu1() = 0; //methode abstraite

Seccretaire doit l'implémenter :
void menu1();
[quote]

Merci encre a vous deux !!!

Cyril Z.
0
cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 123
18 avril 2011 à 20:59
se sont des enseignants chercheurs

Ce n'est malheureusement pas toujours un gage de qualité...
J'ai aussi bossé avec des enseignants chercheurs (qui bossait à mi-temps à Polytechnique et/ou à l'Inria, si vraiment il faut jouer la dessus), et la première chose que l'on a appris, c'est pas de using namespace et pourquoi (et par quoi le remplacer si nécessaire, ou tout du moins l'utiliser correctement si on insiste. Cf l'article dont j'ai mis le lien).

- pour les usings cela vient d'eux et dans une autoformation il l'on utilisé (debut de notre code pour le sujet)

C'est une connerie. Et malheureusement, c'est à cause de gens comme eux, qu'on se retrouve en entreprise avec des conflits de namespace à s'arracher les cheveux.

- pour la verificaétion des deletes c'est pareil c'est "leur code" que j'ai adapté.

Ils ne savent pas que delete 0, ne fait rien ? Pour le coup je suis super étonné de la part de ces enseignants. (Sauf s'ils me répondent: on utilise pas de delete, on a des smart pointers, donc plus l'habitude).

- de meme pour le nom des fichiers pour nous et pour eux (meme lors TD et TP) c'est .cc et .h, autrement dit il ne veulent sans doute pas que l'on utilise .hh

C'est une simple convention. Ça ne change rien. Maintenant, regarde la bibliothèque Boost, tu verras qu'il n'y a pas de .h (Boost est LA bibliothèque la plus évoluée en C++, à tel point que des morceaux de celle-ci sont incorporés à la nouvelle version du C++, le C++0X).

PS: Juste par curiosité, c'est quoi ton école ? Ne réponds pas en public, répond juste par message personnel.
________________________________________________________________________
Historique de mes créations, et quelques articles:
[ http://0217021.free.fr/portfolio http://0217021.free.fr/portfolio]
Merci d'utiliser Réponse acceptée si un post répond à votre question
0
cs_patatalo Messages postés 1466 Date d'inscription vendredi 2 janvier 2004 Statut Modérateur Dernière intervention 14 février 2014 2
18 avril 2011 à 22:29
salut,


Je ne suis pas non plus spécialiste du C++ alors, peut être une réinterpretation de la caste est nécessaire pour appeler des methode de Secretaire alors que l'objet est interprété comme Personne.

@++
0
cs_tiouil Messages postés 51 Date d'inscription dimanche 8 août 2010 Statut Membre Dernière intervention 2 mars 2018
19 avril 2011 à 10:41
Bonjour, patalo (mon idole de visual c++ 2008 ^^), ta reponse me parait bien, mais ..... qu'est ce que la "reinterpretation de la caste" ?

Sinon pour "cptPingu", tu m'as convaincu mais je n'ai pas le temps de revoir entierement mais deux projets, de plus je ne connais pas les fonctions faisant partie de la std a part le "cout<<".

Par contre pour le delete je le fais immediatement

Merci a vous deux !!!

Cyril Z.
0
cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 123
19 avril 2011 à 10:49
@patatalo: Techniquement, c'est juste. Mais au niveau conception, c'est un "workaround", une astuce pour contourner rapidement une erreur de conception à la base. Normalement, s'il utilise "Personne", il doit avoir une méthode héritée par ses fils qui est appelée automatiquement, et donc il n'est pas nécessaire de faire un cast. En revanche, il y a effectivement des cas où on ne peut faire autrement, je suis d'accord avec toi. Ici, on peut heureusement l'éviter.

@tiouil
Par contre pour le delete je le fais immediatement

Tu peux éviter le delete dans certains cas. Ici, tu fais un "new Objet" dans le constructeur et un "delete Objet" dans le destructeur.
Tu peux tout simplement avoir un "Objet" en attribut, au lieu d'avoir un "Objet*". Et la plus besoin de new, ni de delete (Et ça reviens strictement au même, l'objet étant détruit automatiquement à la destruction de son possesseur).

Le mieux c'est que tu me postes un code qui compile, que je puisse t'apporter mon aide correctement :)

________________________________________________________________________
Historique de mes créations, et quelques articles:
[ http://0217021.free.fr/portfolio http://0217021.free.fr/portfolio]
Merci d'utiliser Réponse acceptée si un post répond à votre question
0
cs_tiouil Messages postés 51 Date d'inscription dimanche 8 août 2010 Statut Membre Dernière intervention 2 mars 2018
19 avril 2011 à 11:58
Merci, mais comme je l'ai dit plus haut je me suis arrangé en supprimant la classe personne, car au final secretaire et responsable n'ont rien (fonction) en commum.

Je clos donc le sujet et vous remercie pour m'avoir conseillé pour les usings et delete.



Cyril Z.
0
cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 123
19 avril 2011 à 12:11
En fait, je voulais aussi te corriger certaines erreurs de conception. Mais c'est toi qui voit :)

________________________________________________________________________
Historique de mes créations, et quelques articles:
[ http://0217021.free.fr/portfolio http://0217021.free.fr/portfolio]
Merci d'utiliser Réponse acceptée si un post répond à votre question
0
cs_tiouil Messages postés 51 Date d'inscription dimanche 8 août 2010 Statut Membre Dernière intervention 2 mars 2018
19 avril 2011 à 12:25
Peux-tu juste me dire où et quoi stp ?

Cyril Z.
0
cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 123
19 avril 2011 à 12:37
Peux-tu juste me dire où et quoi stp

Quasi impossible avec si peu de code. Sinon je l'aurai déjà fait.

En faisant des suppositions:
switch (_type)


Du au polymorphisme, normalement, tu n'en as pas besoin.

Responsable* _responsable; /* Supposition, vu que je n'ai pas ton code */
Secretaire* _secretaire;


switch (_type)
{
case responsable :
{
if(_menu == m1)
{
_responsable->menu1();//Erreur de seg
}
else if(_menu == m2)
{
_responsable->menu2();
}
break;
}
case secretaire :
{
if(_menu == m1)
{
_secretaire->menu1(); //Erreur de seg
}
else if(_menu == m2)
{
_secretaire->menu2();
}
break;
}


Devrait être:
  Personne* _personne; /* _personne new Responsable; ou _personne new Secretaire; */


  if(_menu == m1)
   _personne->menu1();
  else if(_menu == m2)
   _personne->menu2();


Vu que je n'ai pas tout ton code, c'était peut être juste. Mais avec le peu de contexte que tu m'as donnée, cette partie me semble étrange.

if(_count_delete < 1)

Très étrange aussi. Mais il me manque trop de donnée pour pouvoir dire si c'est normal ou non.


De même, impossible de savoir s'il faut un seul "Personne" ou deux dans ta classe.

________________________________________________________________________
Historique de mes créations, et quelques articles:
[ http://0217021.free.fr/portfolio http://0217021.free.fr/portfolio]
Merci d'utiliser Réponse acceptée si un post répond à votre question
0
cs_tiouil Messages postés 51 Date d'inscription dimanche 8 août 2010 Statut Membre Dernière intervention 2 mars 2018
19 avril 2011 à 13:10
Felicitations !!!
tu as trouvé la moitié de mon ArchiModele.h,
le count_delete sert a n'effacer qu'une fois car quand je detruit le modele lui meme le delete de secretaire et responsable se passe (ou du moins le pointeurs) et quand le vue (dont je n'ai pas mis le code sur le forum) se detruit, elle refait appel au destructeur de modele car elle a un pointeur sur le modele donc ducoup rebelote (destruction des pointeurs de secr et responsable) -> erreur de seg : mais celle la je l'ai corrigé (tout seul XD)

Sinon comme tu me le reclames tant voici archiModele.h

#ifndef _ARCHI_MODEL_
#define _ARCHI_MODEL_

#include <SFML/System.hpp>
#include <string.h>
#include "ArchiVue.h"
#include "Secretaire.h"
#include "Responsable.h"

using namespace std;

class ArchiModel {
 private:
  int _w, _h;
  
  //definition des énumérations
  enum personne {ttlm, responsable, secretaire};
  enum idMenu {mg, m1, m2};
  enum choix {rien, c1, c2, c3, c4}; 
 
  //specialisation des enum
  enum personne _type;
  enum idMenu _menu;
  enum choix _choix;
  
  Responsable * _responsable;
  Secretaire * _secretaire; 
  
  int _count_delete;

 public:

  ArchiModel();
  ArchiModel(int w, int h);
  ~ArchiModel();
  
  string getType();
  string getIdMenu();
  
  void setIdMenu(string que_fait_on);
  void setChoix(string choix);
    
  void nextStep();  
};
#endif




Cyril Z.
0
cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 123
19 avril 2011 à 13:20
le count_delete sert a n'effacer qu'une fois car quand je detruit le modele lui meme le delete de secretaire et responsable se passe (ou du moins le pointeurs) et quand le vue (dont je n'ai pas mis le code sur le forum) se detruit, elle refait appel au destructeur de modele car elle a un pointeur sur le modele donc ducoup rebelote (destruction des pointeurs de secr et responsable) -> erreur de seg : mais celle la je l'ai corrigé (tout seul XD)


C'est bel et bien un souci. Mais ce n'est pas la bonne manière de le corriger. Ton problème est en amont. Ça veut dire que tu supprimes plusieurs fois ton modele. Et c'est ça que tu dois corriger.


Responsable * _responsable;
Secretaire * _secretaire;

Je n'ai pas le contexte fonctionnel. Est-ce que pour un "ArchiModel" il y a forcément "un responsable ET une secretaire" 1), ou "un responsable OU une secretaire" 2).

Solutions pour 1)

Responsable _responsable; // Pas de pointeurs, on laisse le compilo gérer la mémoire, il le fait très bien :p
Secretaire _secretaire; // Pas d'héritage de "Personne"


Solutions pour 2)

Personne* _personne; // Héritage de "Personne"


________________________________________________________________________
Historique de mes créations, et quelques articles:
[ http://0217021.free.fr/portfolio http://0217021.free.fr/portfolio]
Merci d'utiliser Réponse acceptée si un post répond à votre question
0
cs_tiouil Messages postés 51 Date d'inscription dimanche 8 août 2010 Statut Membre Dernière intervention 2 mars 2018
19 avril 2011 à 13:37
Ben en fait c'est un logiciel permettant d'acceder a une base de données, et une fois le logiciel demarrer on choisi selon que l'on est la secretaire ou le responsable le "bon chemin", et apres des fonctionnalites leurs sont accordées, mais celles ci sont différentes d'une personne a l'autre.

Mais on peut tres bien demarrer le logiciel choisir d'etre le responsable faire un petit "truc" revenir au menu et passer "em mode secretaire" sans quitter le logiciel donc j'ai besoin des deux en meme temps.

Cyril Z.
0
Rejoignez-nous