2011-01-19 3 views
1

Donc je suis un débutant qui essaie de se familiariser avec l'opérateur new. Quel est le problème avec mon destructeur?Opérateur new/delete & destructors

class arr{ 
public: 
    arr(){ 
     pool=::operator new(100*sizeof(double)); 
    } 
    ~arr(){ 
     ::operator delete(pool); 
    } 
    void* pool; 
}; 

int main() 
{ 
    arr a; 
    a.~arr(); //If I comment this out it's ok. 

    void* pool2=::operator new(100*sizeof(double)); //Works 
    ::operator delete(pool2); //Fine. 

    system("pause"); 
    return 0; 
} 

Quitter a. ~ Arr(); en me donne cette erreur:

L'assertion de débogage a échoué! Fichier: Ligne de dbgdel.cpp: 52

Expression: _BLOCK_TYPE_IS_VALID (pHead-> nBlockUse)

Je ne vois pas pourquoi pool2 fonctionne très bien, mais en utilisant la classe me donne des problèmes. Aussi l'erreur n'apparaît qu'après que le système "pauses", ce qui est après un. ~ Arr() s'appelle ???

Merci!

Répondre

7

Eh bien, d'un coup d'œil, vous ne devriez pas appeler explicitement le destructeur. Au lieu de cela, utilisez la portée pour forcer un hors de portée et appelez le destructeur.

int main() 
{ 
    { 
     arr a; 
    } //This calls destructor of a 

    //Rest of code 
} 

Sinon, le destructeur de a est appelé deux fois: une fois lorsque vous l'appelez et à nouveau quand un est hors de portée.

EDIT:

Ici vous allez.

http://www.parashift.com/c++-faq-lite/dtors.html

+1

Lisez aussi la réponse de sbi ci-dessous - vous aurez des problèmes si vous ne déclarez pas un constructeur de copie et un opérateur d'affectation qui garantissent que plusieurs copies d'une instance de arr n'essaient pas de supprimer la même mémoire. – James

6

Le problème est que vous invoquez explicitement la destructor sur a (a.~arr()), tandis que le destructor sera déjà appelé automatiquement lorsque a est hors de portée à la fin de main(). Lorsque le destructeur est appelé pour la deuxième fois, il est appelé sur un objet déjà détruit. Techniquement, cela conduit à Comportement indéfini (ce qui est une manière de dire que tout résultat sera bon selon la norme C++). En pratique, ce code n'exécutera probablement plus que le destructeur, passant l'adresse stockée dans l'emplacement a.pool au ::operator delete() (qui pourrait ou non être ce que le constructeur y a stocké), qui est interceptée par l'exécution de Debug.

Ce que vous devez faire à la place si vous voulez a être supprimé au milieu de main() est d'introduire un champ supplémentaire:

int main() 
{ 
    { 
    arr a; 
    } //a will be deleted here 

    // rest of main 

} 

Une autre façon serait de ne pas utiliser un objet automatique, mais une dynamique un, pour lequel vous pouvez définir une durée de vie.


Mais il y a un autre problème avec votre code, que vous n'avez pas demandé, mais je me sens quand même un besoin de souligner:

Votre classe a besoin de toute urgence une copie constructeur et opérateur d'affectation. (À tout le moins, déclarez-les private afin d'interdire la copie.) Selon le Rule Of Three, le fait que vous ayez besoin d'un destructeur devrait vous indiquer que les deux autres sont également nécessaires.
Vous pouvez éviter tous les tracas en n'essayant pas de gérer manuellement la mémoire allouée dynamiquement. Au lieu de cela, utilisez un type qui le fait pour vous:

class arr{ 
public: 
    arr() : pool(100*sizeof(double)) { 

    } 
    // ~arr() // not needed any longer 
    std::vector<char> pool; 
}; 
0

vous n'avez pas besoin d'appeler destructor pour les objets créés sur la pile. La variable 'a' est en pile et sera supprimée automatiquement en dehors de la portée.

+1

Ce n'est pas seulement que vous "n'avez pas besoin de"; c'est invalide. –

+0

Oui. merci tomalak – blueskin