Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
3190 connectés 

  FORUM HardWare.fr
  Programmation

  C++ Pb de libération de memoire.

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

C++ Pb de libération de memoire.

n°18170
oliv5
Pourquoi ? Parce que !
Posté le 12-03-2001 à 10:06:27  profilanswer
 

C'est un problème tres con, mais bon, y en a marre : impossible de libérer un objet qui se trouve dans une liste chainee.
Bon, c'est trop con, alors vite, répondez.

mood
Publicité
Posté le 12-03-2001 à 10:06:27  profilanswer
 

n°18171
darkoli
Le Petit Dinosaure Bleu
Posté le 12-03-2001 à 10:17:30  profilanswer
 

il faudrait plus de precisions :
  -> structure de la liste chainée
  -> comment est créé l'objet
  -> comment tu fais pour libérer la mémoire

n°18229
oliv5
Pourquoi ? Parce que !
Posté le 12-03-2001 à 15:04:13  profilanswer
 

Je n'ai pas le source sous les yeux (ce soir, je le mettrais), mais c'est simple, ma liste chainee prend un pointeur (void*) vers un objet quelconque.
je fais :  
 
Obj* monObj = new Obj();
maliste->add((void*)monObj);
 
et voila, j'ai un objet à la suite de ma liste.
Pour le libérer, j'ai une méthode qui parcourt la liste et qui fait : delete monObj;
sachant que monObj et l'objet qui se trouve à la fin de la liste. Ensuite, on remonte jusqu'au debut en désallouant l'objet au passage.
Ca me plante méchamment à la gueule. Bouhhhh.

n°18230
verdoux
And I'm still waiting
Posté le 12-03-2001 à 15:10:44  profilanswer
 

Ben c'est comme ça qu'on fait en principe. Donc tu dois avoir fait une erreur dans le code.

n°18231
n0mad
inscrit au XXe siècle
Posté le 12-03-2001 à 15:12:51  profilanswer
 

C'est normal : comment veux-tu libérer un void* ?
 
Si delete est utilisé avec un scalaire (int, char, float etc...), il libère l'espace mémoire
 
S'il est appelé avec une classe, c'est le destructueur (virtuel) de la classe qui est appelé.
 
Void n'est pas le "type à tout faire" mais au contraire, une absence de type.
 
Pour résoudre ton problème, il faut que les atomes de ta liste dérivent d'une classe avec un destructeur virtuel. Ensuite, chaque sous-classes pourra spécialiser son destructeur : c'est le but de la programmation objet !


---------------
Pipiru piru piru pipiru pi
n°18234
oliv5
Pourquoi ? Parce que !
Posté le 12-03-2001 à 15:20:01  profilanswer
 

certes, je fais un delete sur un void, mais comme tous les objets que j'insere derivent d'une classe A de base, je fais un cast avant, comme ceci : delete (A*)monObj.
Mais apparemment, il ne libère pas toute la mémoire, mais seulement celle que prend un objet A et non pas celle d'un objet B qui dérive (et qui est + gros).
 
Toi, tu voudrais qu'au lieu d'un pointeur de type void je mette un pointeur vers un objet de base dont la classe possede un destructeur ?? je vois pas trop.
 
Ha, sinon, un objet ne peut pas par hazard se libérer à la fin de son destructeur ?

n°18235
n0mad
inscrit au XXe siècle
Posté le 12-03-2001 à 15:24:22  profilanswer
 

>j'insere derivent d'une classe A de base, je fais un cast  
>avant, comme ceci : delete (A*)monObj.
>Mais apparemment, il ne libère pas toute la mémoire, mais  
>seulement celle que prend un objet A et non pas celle d'un  
>objet B qui dérive (et qui est + gros).
 
Ah ok, c'est bon alors. S'il appelle le destructeur du type du pointeur et non le destructeur du type de la classe, c'est que ton destructeur n'est pas virtuel : tu as vérifié ?


---------------
Pipiru piru piru pipiru pi
n°18237
oliv5
Pourquoi ? Parce que !
Posté le 12-03-2001 à 15:28:27  profilanswer
 

Haaaa, c'est pas con ca. Mais il faudrait qu'un objet puisse lui meme dans son code se desallouer. Donc, est ce que je peux mettre la ligne : delete this à la fin du destructeur d'un objet. C'est un peu bizarre, mais ca serait tellement pratique.

n°18238
verdoux
And I'm still waiting
Posté le 12-03-2001 à 15:36:31  profilanswer
 

delete this dans le destructeur est une mauvaise idée puisque delete appelle le destructeur :D

 

[edit]--Message édité par Verdoux--[/edit]

n°18239
verdoux
And I'm still waiting
Posté le 12-03-2001 à 15:41:09  profilanswer
 

Il faut virer le void* de la def de ta liste. Tu peux utiliser un template pour ça ( ou alors carrément utiliser les listes déjà définies dans la STL).
Et puis toujours mettre un destructeur virtuel dans une classe de base (dans 99% des cas).

mood
Publicité
Posté le 12-03-2001 à 15:41:09  profilanswer
 

n°18240
n0mad
inscrit au XXe siècle
Posté le 12-03-2001 à 15:42:11  profilanswer
 

>Mais il faudrait qu'un objet puisse lui meme dans son code se  
>desallouer. Donc, est ce que je peux mettre la ligne : delete  
>this à la fin du destructeur d'un objet. C'est un peu bizarre,  
>mais ca serait tellement pratique.
 
Je comprends pas vraiment ton probleme. le keyword delete appelle justement le destructeur d'une classe et libere l'espace mémoire aloué. Tu n'as pas besoin de faire "delete this" (j'ajouterais qu'il ne faut pas sinon ca part en recursion, enfin j'ai pas testé).
 
Tu veux faire des objets qui se liberent automatiquement, il faut que tu codes un système de "garbage collecting" à la java.  
 
Une solution plus simple qui evite les parcours dans tous les sens d'une liste, c'est d'abonner au moment de la création chaque objet créé à une classe qui va stocker les pointeurs vers les instances courantes. Tu pourra ainsi les effacer quand tu veux.


---------------
Pipiru piru piru pipiru pi
n°18241
oliv5
Pourquoi ? Parce que !
Posté le 12-03-2001 à 15:45:06  profilanswer
 

Haaaaaa, delete, j'avais pas pigé. Et que fais tu dans ton destructeur ? (mis a part les actions eventuelles sur d'autres objets?)
Tu tapes quoi, par exemple ?

n°18243
oliv5
Pourquoi ? Parce que !
Posté le 12-03-2001 à 15:50:26  profilanswer
 

"Il faut virer le void* de la def de ta liste. Tu peux utiliser un template pour ça ( ou alors carrément utiliser les listes déjà définies dans la STL). "
 
=====> les templates, j'y ai pas encore touché. t'as un exemple, stp.
=====> c'est quoi la STL (oui, je ne sais pas grand chose en C++, mais bon, mon rayon c'est + le java).
 
"Et puis toujours mettre un destructeur virtuel dans une classe de base (dans 99% des cas). "
=====> ca OK, je vais le faire. Mais le pb, c'est que j'ai des tonnes de classes dérivées. Un bonne quinzainne... ca fait chier de redefinir tant de fois un destructeur.

n°18246
n0mad
inscrit au XXe siècle
Posté le 12-03-2001 à 16:03:46  profilanswer
 

oliv5> voici un exemple:
 
class MaClass {
 
protected:
    int unEntier;  
    float unFloat;
    int* unPointeur;
    int* unTableau;  // un pointeur sur un objet créé dans la classe
    Obj obj1;
    Obj* obj2; // un pointeur sur un objet créé dans la classe
 
public:
MaClass() {
   unTableau = new int[10];
   obj2 = new Obj;
}
 
virtual ~MaClass() {
   delete[] unTableau;
   delete obj2;
// tout le reste est libéré automatiquement
}
 
}


---------------
Pipiru piru piru pipiru pi
n°18248
verdoux
And I'm still waiting
Posté le 12-03-2001 à 16:08:06  profilanswer
 

Et il faudrait planquer le constructeur par copie et l'opérateur d'affectation sinon ça peut merder.

n°18254
verdoux
And I'm still waiting
Posté le 12-03-2001 à 16:30:26  profilanswer
 

Les templates ou patrons de classes permettent de définir des familles de classes à partir d'une seule, grâce à une paramétrisation.  
 
La STL est un ensemble de telles classes. (voir http://www.sgi.com/tech/stl/ )
 
Par exemple:
list<int> liste_d_entiers; // est une liste contenant des entiers.
Et list<Objet*> liste_d_objets est une liste de pointeurs sur des Objets.
 
Pour remplir ma liste_d_entiers:
for(int = 0; i < 10; i++)
 list_d_entier.push_back(i);
 
Pour la pourcourir:
for(list<int>::iterator it = liste_d_entiers.begin(); it != liste_d_entiers.end(); ++it)
 cout << *it << endl;
 
Là on voit apparaître un type d'objet liés aux classes de conteneurs de la STL, les itérateurs.
Un peu comme un pointeur pour les listes "classiques" ou les tableaux, un itérateur permet de parcourir les éléments d'un conteneur.

 

[edit]--Message édité par Verdoux--[/edit]

n°18255
[FDS]
Posté le 12-03-2001 à 16:37:17  profilanswer
 

VIVE JAVA !!! :D  :D  :D

n°18580
oliv5
Pourquoi ? Parce que !
Posté le 14-03-2001 à 12:57:55  profilanswer
 

Ha, Ok, je vais essayer le coup des templates.

n°18601
XuTi
Posté le 14-03-2001 à 15:54:55  profilanswer
 

y a un truc qui me chifonne...

Citation :


oliv5 :certes, je fais un delete sur un void, mais comme tous les objets que j'insere derivent d'une classe A de base, je fais un cast avant, comme ceci : delete (A*)monObj.  
Mais apparemment, il ne libère pas toute la mémoire, mais seulement celle que prend un objet A et non pas celle d'un objet B qui dérive (et qui est + gros).


en clair tu as ca:
         derivation
objetA ------------> objetB
et apres tu fais ca:
 
objetB* monObj = new objetB();
maliste->add((void*)monObj);
 
et pour effacer monObj tu fais dans ta liste:
delete (objetA*)monObjDansLaListe;
 
et apres tu trouves illogique que la liberation memoire n a pas ete effectue correctement... mais si tu regardes bien c normal...
 
1- la declaration objetB doit surrement contenir plus de proprietes que objetA (par derivation sinon pas la peine de le faire), donc quand tu fais delete (objetA*)monObjDansLaListe tu detruis un objet de de type objetA... donc destruction qui ne prend pas en compte les definitions de l objetB
 
2- comme j ai dit precedemment tu fais appel au destructeur de l objetA au lieu de destructeur de l objetB ... ce qui est pas logique

n°18605
n0mad
inscrit au XXe siècle
Posté le 14-03-2001 à 16:08:51  profilanswer
 

>2- comme j ai dit precedemment tu fais appel au destructeur de >l  
>objetA au lieu de destructeur de l objetB ... ce qui est pas  
>logique  
 
C'est tout à fait logique si le destructeur est virtuel.


---------------
Pipiru piru piru pipiru pi
n°18986
oliv5
Pourquoi ? Parce que !
Posté le 17-03-2001 à 14:53:18  profilanswer
 

Bouhouhouhou, j'y comprend rien du tout. J'ai essayé plein de trucs, dont les destructeurs virtuels qui semblaient logiques, mais ca ne marche pas comme je veux. Alors j'ai essayé un truc tout con : j'appelle delete sur une classe toute simple (pas d'heritage, de derivation ou quoi que ce soit) et malgré ca, l'objet est encore en mémoire (je peux lire ses variables etc...)
 
je ne comprend pas.

n°18988
verdoux
And I'm still waiting
Posté le 17-03-2001 à 15:04:54  profilanswer
 

Je pense que même si tu libères la mémoire, en inspectant ensuite la zone occupée par l'objet, tu pourras lire ses variables dans le dernier état occupé.
Simplement cette zone n'est plus utilisée et libre pour des allocations ultérieures.

n°18989
oliv5
Pourquoi ? Parce que !
Posté le 17-03-2001 à 15:13:41  profilanswer
 

j'espère que tu as raison. Mais j'ai beau faire plein de création d'objets apres, il n'ecrase pas l'objet désalloué.

n°18995
oliv5
Pourquoi ? Parce que !
Posté le 17-03-2001 à 16:17:23  profilanswer
 

J'ai trouvé !!!!!!! En fait, dans ma liste chainée d'objets, un même objet peut être en double, triple, etc... et quand je libère la mémoire la première fois, ca marche, mais la deuxième .... ca plante.

n°19001
verdoux
And I'm still waiting
Posté le 17-03-2001 à 18:09:19  profilanswer
 

Dans ce cas il faut utiliser des "pointeurs intelligents" (avec compteur de référence)

n°19012
oliv5
Pourquoi ? Parce que !
Posté le 17-03-2001 à 20:26:05  profilanswer
 

des pointeurs quoi ???
bon, expliques.
Pour le moment, j'ai fait une liste chainee des objets deja libérés et ca a l'air de marcher. MAis bon, apres il faut libérer la liste chainee... alors si tu as une autre solution, ca me va.

n°19120
LeGreg
Posté le 18-03-2001 à 16:48:07  profilanswer
 

Deja regarde quels sont tes besoins!
 
si tu peux placer des copies d'objets dans
ta liste, pas besoin de compter les references.
(chaque clone d'objet ne sera physiquement present qu'en un seul endroit de ta liste)
 
Si vraiment tu ne peux pas faire autrement, ce que tu peux faire c'est faire en sorte que les objets que tu places dans ta liste realisent une interface "comptable" avec un entier compteur, et deux methodes inc_reference, dec_reference. Ainsi lorsqu'un objet est ajoute a la liste on incremente son compteur et lorsqu'il est enleve, on decremente son compteur, ainsi lorsque ce compteur arrive a zero tu sais qu'il n'y a plus de references a cet objet et c'est la que tu fais le delete.
 
Si tu cherches bien tu trouveras des implantations plus complexes de smart-pointers sur le web.
 
A+
LeGreg

mood
Publicité
Posté le   profilanswer
 


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation

  C++ Pb de libération de memoire.

 

Sujets relatifs
problème de mémoire XMS avec un 386[Javascript] Limitation de mémoire @ déclarations de vars/arrays ?
ajout de mémoireplace mémoire dispo en C++
Plus de sujets relatifs à : C++ Pb de libération de memoire.


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR