Se connecter / S'enregistrer
Votre question

Problème de glibc en C++

Tags :
  • Serveur
  • Programmation
Dernière réponse : dans Programmation
19 Février 2009 17:18:12

Bonjour tous le monde,

je programme actuellement un serveur en C++ dans lequel j'ai une classe "Trame".

Je possède donc une fichier "Trame.cpp" et "Trame.h".

J'ai cependant un problème que je ne comprend pas, lorsque je fais :
  1. Trame trame;
  2. ...
  3. trame = Trame(param1, param2, ...);


J'ai une erreur :
...glibc..."multiple free or corruption" pile sur l'adresse de ma Trame.

Je vous donne les codes, ce sera plus parlant :

Trame.cpp
  1. Trame::Trame(V_Mode action, int taille, char* data){
  2. printf("Appel au gros constructeur\n");
  3. printf("trame début constructeur : %p\n", _trame);
  4. /**ALLOCATION**/
  5. _trame = new char[6+taille];
  6. /**DEBUT**/
  7. _trame[0] = 0x11;
  8. _trame[1] = 0x5F;
  9.  
  10. /**ACTION**/
  11. _trame[2] = action;
  12.  
  13. /**TAILLE**/
  14. _trame[3] = taille;
  15.  
  16. /**CHARGEMENT DES DONNEES**/
  17. for(int i=4; i < taille+4; i++){
  18. _trame[i] = data[i-7];
  19. }
  20.  
  21.  
  22. /**FIN**/
  23. _trame[taille+4] = 0x0D;
  24. _trame[taille+5] = 0x0A;
  25.  
  26. printf("trame fin constructeur : %p\n", _trame);
  27. }
  28.  
  29. Trame::Trame(){
  30. printf("Appel au petit constructeur\n");
  31. printf("trame début constructeur : %p\n", _trame);
  32. _trame = NULL;
  33. printf("trame fin constructeur : %p\n", _trame);
  34. }
  35.  
  36. Trame::~Trame(){
  37. printf("Appel destructeur\n");
  38. printf("trame début destructeur : %p\n", _trame);
  39. if(_trame != NULL){
  40. printf("la trame n'est pas nulle => delete\n");
  41. delete [] _trame;
  42. }



main.cpp

  1. int main(int argc, char* argv[])
  2. {
  3. int socket;
  4. struct sockaddr_in serveur;
  5. // char donnees[] = {1, 2, 3, 4};
  6. Trame trame;
  7. cout << endl << "-------------------------" << endl;
  8.  
  9. trame = Trame(V_R_POSITION_MOT_G, 0, NULL);
  10.  
  11. cout << endl << "-------------------" << endl;
  12.  
  13. //Création du socket:
  14. socket = creationSocket();
  15. cout << "socket ok" << endl;
  16. ...


Merci d'avance

Autres pages sur : probleme glibc

a b L Programmation
19 Février 2009 20:44:21

Quand tu fais "Trame trame;", tu instancies un premier objet.
Quand tu fais "trame = Trame(V_R_POSITION_MOT_G, 0, NULL);", tu instancies un second objet (temporaire), et tu utilises l'opérateur d'affectation pour copier le nouvel objet dans l'ancien.
Pour maitriser ça, il te faut avoir défini le constructeur qui va bien, un constructeur par défaut et l'opérateur d'affectation = (ce qui ne semble pas être ton cas).

Si tu avais fait "Trame trame = Trame(V_R_POSITION_MOT_G, 0, NULL);", tu n'instancierais qu'un seul objet sans utiliser l'opérateur d'affectation.
Pour maitriser ça, il suffit d'avoir défini le constructeur qui va bien.

Pour préciser ton problème, lorsque tu instancies le second objet, il est instancié de façon temporaire sur la ligne. C'est-à-dire qu'à l'instruction suivante (juste avant le "cout" suivant), cet objet temporaire est détruit. Comme tu n'as pas fait d'opérateur d'affectation, par défaut ça copie tout ce qui est directement dans la classe. Donc, dans la variable "trame", tu copie le pointeur (qui n'est qu'une adresse mémoire), mais pas de contenu ! Du coup, lorsque l'objet temporaire est détruit, ton pointeur pointe sur une zone mémoire désallouée qui génère un petit crash.

Donc, je te donnerais 2 conseils pour éviter ce genre de problème:
1. Evite de déclarer ta variable ailleurs que lors de l'instanciation (le "=" n'as pas la même signification dans ce cas, car c'est un simple appel au constructeur), mais ce n'est pas toujours possible (c'est possible dans ton cas).
2. Utilise la forme de Coplien dans toutes tes classes, même si tu n'en vois, a priori, pas l'utilité (car on ne peut pas penser à tout).
La forme canonique de Coplien consiste à toujours définir:
- le constructeur par défaut (ou un constructeur avec tous les paramètres ayant des valeurs par défaut, implicitement appelé lors d'une instanciation temporaire)
- le constructeur par recopie (implicitement appelé lors d'un "TaClasse * pClasse = new TaClasse( uneAutreClasse );"
- le destructeur (implicitement appelé lors de la fin de définition de variable comme une fin de fonction, fin d'un block if, etc, ou encore une instanciation temporaire)
- L'opérateur d'affectation = (implicitement appelé lors d'un "classe = uneAutreClasse;")
m
0
l
20 Février 2009 09:20:14

J'ai effectivement regardé mes projets C++ de l'année dernière qui m'ont rappelé pas mal de choses.

En effet j'avais oublié de faire le constructeur par recopie.

Ca m'a aussi rappelé la surchage d'opérateurs qui est ici un autre de mes problèmes.

En gros il faut que je fasse ces deux points et normalement ça passera.

Merci beaucoup.
m
0
l
Tom's guide dans le monde
  • Allemagne
  • Italie
  • Irlande
  • Royaume Uni
  • Etats Unis
Suivre Tom's Guide
Inscrivez-vous à la Newsletter
  • ajouter à twitter
  • ajouter à facebook
  • ajouter un flux RSS