[C++] question de delete sur une hiérarchie de classe

question de delete sur une hiérarchie de classe [C++] - Programmation

Marsh Posté le 04-12-2001 à 23:40:37    

voilà je me suis la tête avec un plantage sur un delete :
d'abord un code exemple du problème
 
class CompteurDeReferences
{
public :
     CompteurDeReferences( );
 ~CompteurDeReferences( ) { };
 void AjouteReference( );
 void Relache( );
private:
 int _MonCompteurDeReferences;
};
 
 
CompteurDeReferences::CompteurDeReferences( )
{
 _MonCompteurDeReferences = 0;
}
 
void CompteurDeReferences::AjouteReference( )  
{  
 ++_MonCompteurDeReferences;  
}
 
void CompteurDeReferences::Relache( )  
{  
 if( --_MonCompteurDeReferences == 0 )
 {
  delete this;
 }
}
 
class A : public CompteurDeReferences
{
public:
 virtual int get( ) { return 5; }
 ~A( ) { }
};
 
void main( )
{
 A* p = new A;
 
 p->AjouteReference( );
 
 p->Relache( );
 
}
 
Sur le delete du Relache le delete se plante.
L'objet A se compose donc au début de la classe CompteurDeReferences puis un pointeur vers la vtable de A.
Et donc dans le delete comme ~CompteurDeReferences n'est pas
virtuel c'est seulement le destructeur de CompteurDeReferences  
qui est appelé et pas celui de A. Bon ok mais alors pourquoi ça plante ? j'arrive pas à comprendre.
Si on met au moins une méthode virtuelle dans CompteurDeReferences ça passe. Quelqu'un a-t-il une idée ?
Je sais que de toute façon dans une hiérarchie faut que la classe la plus haute soit polymorphe mais j'aimerais comprendre quand même pourquoi ça marche pas.
De plus est-ce que lorsque un destructeur est virtuel dans une classe X, n'importe quel destructeur d'une fille de X l'est ?
 
Merci.:)

Reply

Marsh Posté le 04-12-2001 à 23:40:37   

Reply

Marsh Posté le 05-12-2001 à 00:14:17    

La partie exclusivement A de l'objet n'est pas détruite par le delete this si le destructeur n'est pas virtuel.

Reply

Marsh Posté le 05-12-2001 à 05:50:09    

Verdoux a écrit a écrit :

La partie exclusivement A de l'objet n'est pas détruite par le delete this si le destructeur n'est pas virtuel.  




 
ok ça je le savais mais ce que je ne comprend pas c'est pourquoi ça plante. Si on une méthode virtuelle ( autre que le destructeur ), ça ne plante pas et la partie A n'est pas détruite non plus.

Reply

Marsh Posté le 05-12-2001 à 09:09:59    

Mais t vraiement sur que ton objet peut se détruire lui même !?
tu crois pas que t plutot obligé de faire direcement un appel au delete de l'instance dans la classe utilisatrice ?
D'ailleur, ce qui serai plus logique, c que le code que tu mets dans Relache, tu le mettes dans ton destructeur, et pif paf, plus de méthode relache. plus d'emmerdements !:D

Reply

Marsh Posté le 05-12-2001 à 09:17:39    

ayachi a écrit a écrit :

 
 
ok ça je le savais mais ce que je ne comprend pas c'est pourquoi ça plante. Si on une méthode virtuelle ( autre que le destructeur ), ça ne plante pas et la partie A n'est pas détruite non plus.  




Ca plante car tu ne detruit pas A mais uniquement Compteur de reference qui est dans A. Ton destructeur doit etre virtuel, pour que la methode puisse marcher...
En effet le delete this doit etre vu comme un appel au destructeur, et la tu appelle le destructer de Compteur de reference uniquement, et pas celui de A...

Reply

Marsh Posté le 05-12-2001 à 11:45:10    

hum...  
Je suis pas certain a 100% mais il me semble quand meme que tu peux pas detruire un objet dans une de ses methodes.
La methode fait partie de l'objet alloue. Si tu liberes la mémoire, au retour de delete, tu te retrouves dans...  
bah en tous cas, tu devrais te retrouver dans la methode. Mais comme l'objet a ete desalloue...

Reply

Marsh Posté le 05-12-2001 à 11:58:31    

Bon ce qu'il faut faire , c'est super simple:
Ta fonction Relache ne doit pas faire un delete mais juste Decrementer le compteur de Référence,
et dans ton main tu dois faire un delete de A pour que l'objet soit desalloué.

Reply

Marsh Posté le 05-12-2001 à 13:26:15    

clemarch > c'est justement ce qu'il ne veut pas faire...
 
darthguy > cela ne pose aucun probleme tant que l'on ne fais plus reference a l'objet...
Le theme de l'objet sucidaire est un grans classique. le delete doit etre la derniere instruction faisant reference a l'objet, ce qui n'est pas si evident que cela avec des methodes polymorphes...

Reply

Marsh Posté le 05-12-2001 à 13:30:30    

darthguy a écrit a écrit :

hum...  
Je suis pas certain a 100% mais il me semble quand meme que tu peux pas detruire un objet dans une de ses methodes.
La methode fait partie de l'objet alloue. Si tu liberes la mémoire, au retour de delete, tu te retrouves dans...  
bah en tous cas, tu devrais te retrouver dans la methode. Mais comme l'objet a ete desalloue...


c'est tout à fait possible, c'est comme ça que marche 3d studio max.

Reply

Marsh Posté le 05-12-2001 à 17:41:26    

darthguy a écrit a écrit :

hum...  
Je suis pas certain a 100% mais il me semble quand meme que tu peux pas detruire un objet dans une de ses methodes.
La methode fait partie de l'objet alloue. Si tu liberes la mémoire, au retour de delete, tu te retrouves dans...  
bah en tous cas, tu devrais te retrouver dans la methode. Mais comme l'objet a ete desalloue...  




 
Bah pour tout le standard COM ( et tous les logiciels qui vont avec IE, windows, DirectX, Office et des milliers d'autres ) c'est comme ça que ça marche, dans la fonction fondamentale
IUnknown::Release( ).
Sinon je reprécise, le fait que le destructeur soit virtuel
n'est pas indispensable pour que ça ne plante pas ( mais indispensable sinon pour bien coder ) mais il faut qu'au moins
une méthode soit virtuelle, et là y'a que le destructeur de Compteur qui est appelé et pas celui de A.
Il faut que je comprenne, je vais y arriver ... :)

Reply

Marsh Posté le 05-12-2001 à 17:41:26   

Reply

Marsh Posté le 05-12-2001 à 17:53:10    

Mais tu s sur que c'est sur le delete qu'il plante et pas sur le retour du release ?  
Ou meme la fin de ton prog ?
Car logiquement ce que tu as alloue dans ton prog est libere a la fin... donc p est libere et l'est deja a moitier...
 
A propos le but c'est de faire des smart pointer ?

 

[edtdd]--Message édité par BENB--[/edtdd]

Reply

Marsh Posté le 05-12-2001 à 17:56:42    

BENB a écrit a écrit :

Mais tu s sur que c'est sur le delete qu'il plante et pas sur le retour du release ?  
Ou meme la fin de ton prog ?
Car logiquement ce que tu as alloue dans ton prog est libere a la fin... donc p est libere et l'est deja a moitier...
 
A propos le but c'est de faire des smart pointer ?  
 
 




 
ouais c'est pour être utilisé avec des smart pointer
Non c'est sur le delete this, certain ( sauf si le debugger m'aurait menti à l'insu de mon plein gré :) )

Reply

Marsh Posté le 05-12-2001 à 18:01:42    

ayachi a écrit a écrit :

 
 
ouais c'est pour être utilisé avec des smart pointer
Non c'est sur le delete this, certain ( sauf si le debugger m'aurait menti à l'insu de mon plein gré :) )  




Pourquoi ne pas utiliser template et procuration plutot ?
Un compteur de reference dans une classe template qui point sur ton type, comme cela plus besoin de cet heritage...
 
Je suis desolee... je ne reponds pas a la question mais a comment faire autrement :D

Reply

Marsh Posté le 05-12-2001 à 18:05:18    

BENB a écrit a écrit :

 
Pourquoi ne pas utiliser template et procuration plutot ?
Un compteur de reference dans une classe template qui point sur ton type, comme cela plus besoin de cet heritage...
 
Je suis desolee... je ne reponds pas a la question mais a comment faire autrement :D  




 
Donnes un bout de code pour voir stp

Reply

Marsh Posté le 05-12-2001 à 18:16:09    

template <class T>
class RefCounter
{
public:
   RefCounter(T&);
   RefCounter(RefCounter<T> );
   ~RefCouneter();
   T& operator*();
   T* operator->();
   IncCounter();
   DecCounter();
private:
   T* Target;
   int Counter
}; // grosso modo...
 
L'intetet c'est qu'ensuite pour chaque classe tu choisit si tu veux un smart pointer ou pas...

 

[edtdd]--Message édité par BENB--[/edtdd]

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed