2009-01-14 5 views
1

Hé les gars, j'ai écrit un test rapide. Je veux supprimer pour appeler deleteMe qui va ensuite supprimer lui-même. Le but de ceci est que je peux supprimer obj normalement qui sont alloués par un lib. (Je ne veux pas d'accidents dus à crt ou w/e). Avec cette suppression, j'obtiens un stackoverflow, sans que msvc dise que j'ai perdu 4 octets. Quand je n'appelle pas le test je fuis 0. Comment est-ce que je supprime sans un problème de récurrence? -edit- pour que cela soit plus clair. Je veux que le LIB appeler supprimer (ainsi DeleteMe) au lieu du programme en raison de crtsurcharge de surcharge, débordement récursive

class B 
{ 
public: 
    virtual void deleteMe()=0; 
    static void operator delete (void* p) { ((B*)p)->deleteMe(); } 
}; 

class D : public B 
{ 
public: 
    void deleteMe()  { 
     delete this; 
    } 
}; 

int test() 
{ 
    B *p = new D; 
    delete p; 
    return 0; 
} 

Répondre

1

La récursion est due à deleteMe appelant delete, qui appelle B operator delete qui appelle à nouveau deleteMe. Il est correct de surcharger operator delete (bien que vous surchargiez habituellement aussi operator new), en particulier lorsque vous manipulez des objets "étrangers", ce qui est probablement votre cas, mais vous devez à son tour appeler la routine de nettoyage réelle depuis le delete personnalisé. Dans le cas général, un operator delete surchargé doit correspondre au operator new. Dans votre cas:

B *p = new D; 

Ici p est attribuée à la new mondiale, il doit être libéré avec l'delete mondiale. Donc:

class D : public B 
{ 
public: 
    void deleteMe()  { 
     ::delete this; 
    } 
}; 
+0

la routine de nettoyage est la plupart du temps dans le dtor, je voudrais supprimer l'objet avec suppression normale et l'allouer avec le nouveau normal. Comment est-ce que je fais ceci sans un problème de récurrence? –

1

Vous ne devriez pas surchargez supprimer. Surtout pas à une fonction qui finit par appeler delete. Toute libération de mémoire que vous devez faire (et vous n'avez pas besoin d'en faire dans cet exemple) devrait être faite dans un destructeur.

0

Il est probablement préférable d'avoir une méthode Destroy() que vos clients doivent appeler ... cela protégera votre lib des différences dans le tas.