2017-07-27 6 views
0

J'ai créé une classe nommée cell. Dans cette classe, il y a un tableau de pointeurs cell. L'en-tête ressemble à ceci:Destructeur plantant lors de la suppression d'un tableau de pointeurs en C++

class cell 
{  
public: 
    cell(); 
    cell *c[8]; 
    void creatcells(); 
    virtual ~cell(); 
    .. 

} 

et le fichier cpp ressemble à ceci:

cell::cell() 
{ 
//ctor 
for(int i=0;i<8;i++) 
{ 
    c[i]=NULL; 
} 

} 


void cell::creatcells() 

{ 
    cell c1,c2,c3,c4,c5,c6,c7,c8; 

    c[0]=&c1; 
    c[1]=&c2; 
    c[2]=&c3; 
    c[3]=&c4; 
    c[4]=&c5; 
    c[5]=&c6; 
    c[6]=&c7; 
    c[7]=&c8; 
} 

cell::~cell() 
{ 
    for(int i=0; i<8; i++) 
    { 
     if (c[i]!=NULL) 
     { 
        delete c[i]; 
     } 
    } 
    delete[] c; 

} 

Mais chaque fois que se termine le programme, il se bloque, pourquoi? Je ai essayé sans if (c[i]!=NULL), mais cela ne aide pas. Seulement sans la boucle for le code se termine parfaitement, mais je sais que cela doit être supprimé aussi. Je pense que j'ai écrit le destructeur correctement, n'est-ce pas?

+0

Ouvrir le programme avec le débogueur et il va se casser sur le point de crash – user5821508

+3

'cellule c1, c2, c3, c4, c5, c6, c7, c8;' <- tous sont hors de portée à la fin de la méthode et l'adresse n'est pas valide. – crashmstr

+2

Aucune des variables 'c1',' c2', etc n'existe en dehors de la portée de la fonction 'createcells'. Donc stocker des pointeurs sur eux va vous amener à avoir un tableau plein de pointeurs qui pendent. – CoryKramer

Répondre

5
void cell::creatcells() 
{ 
    cell c1,c2,c3,c4,c5,c6,c7,c8; 

    c[0]=&c1; 
    c[1]=&c2; 
    ... 

Tous les objets cell ci-dessus sont détruits automatiquement à la fin de createcells() .Donc delete c[i]; dans destructor est UB.What que vous voulez est

c[0]= new cell(); 
c[1]= new cell(); 
+3

Ce que vous * voulez * vraiment, c'est un 'std :: vector ' et une optimisation de la valeur de retour! – Bathsheba

+0

En procédant ainsi, dois-je les supprimer comme avant? ou sont-ils détruits? J'ai changé le code comme vous l'avez suggéré et j'ai gardé mon destructeur comme avant, mais il plante de nouveau ... –

+0

@NoamChai 'delete [] c;' Vous n'en avez pas besoin puisque vous avez déjà supprimé tous les objets de la boucle. –

4

Vous tentez de déréférencer les pointeurs vers et delete variables qui avaient une durée de stockage automatique et ne sont plus dans la portée! Votre compilateur ne vous a-t-il pas averti de cela?

Le comportement de votre programme est donc undefined.

Vous ne jamais paire un delete[] avec un new[] et un delete avec un new; Bien que vous pouvez déléguer le delete (et même le new) à une classe de pointeur géré comme std::unique_ptr. Pourquoi ne pas refactoriser à std::vector<cell> et utiliser optimisation de valeur de retour?


std::make_unique utilisant.

+0

... et de déléguer le 'new' à' std :: make_unique' –

+0

@MartinBonner: Merci, nicked que. – Bathsheba

3

En fonction cell::createcells les variables sont locales et sortir de la portée et sont détruits une fois que la fonction retourne. Ces objets n'existeront pas lorsque vous essaierez de les supprimer. Le déréférencement de ces pointeurs conduira à undefined behavior. Pour ne pas mentionner que vous devriez seulement delete ce que vous new. Et puisque vous ne faites new rien faire delete sur les pointeurs à nouveau conduit à undefined behavior.

La solution simple est d'utiliser un vector de objets:

std::vector<cell> c; 

Ensuite, il suffit d'ajouter huit cell objets au vecteur:

void cell::creatcells() 
{ 
    c = std::vector<cell>(8); 
} 

Maintenant, le vecteur contiendra huit défaut construit cell objets. Pas besoin de faire quoi que ce soit dans le constructeur ou le destructeur. En fait, je vous recommande de supprimer complètement le constructeur et le destructeur conformément à the rule of zero.