2017-07-27 8 views
0

Ich machte eine Klasse mit dem Namen cell. Innerhalb dieser Klasse gibt es eine Reihe von cell Zeigern. Der Header sieht wie folgt aus:Destruktor Absturz beim Löschen eines Arrays von Zeigern in C++

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

} 

und die cpp Datei sieht wie folgt aus:

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; 

} 

Aber jedes Mal, endet das Programm, es stürzt ab, warum?
Ich versuchte ohne if (c[i]!=NULL), aber das hilft nicht. Nur ohne die for-Schleife endet der Code einwandfrei, aber ich weiß, dass dies auch gelöscht werden muss. Ich glaube, ich habe den Destruktor korrekt geschrieben, oder?

+0

Öffnen Sie Programm mit Debugger und es bricht Crashpunkt – user5821508

+3

'Zelle C1, C2, C3, C4, C5, C6, C7, C8;' <- alle diese sind am Ende der Methode und Die Adresse ist nicht gültig. – crashmstr

+2

Keine der Variablen 'c1',' c2' usw. existiert außerhalb des Geltungsbereichs der Funktion 'createcells'. Das Speichern von Zeigern führt dazu, dass Sie ein Array voller fliegender Zeiger haben. – CoryKramer

Antwort

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

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

Alle oben cell Objekte werden am Ende des createcells() .So delete c[i]; in destructor automatisch zerstört ist UB.What Sie wollen,

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

Was Sie * wirklich * wollen, ist ein 'std :: vector ' und Rückgabewertoptimierung! – Bathsheba

+0

Muss ich sie so löschen, wie ich es vorher getan habe? oder sind sie zerstört? Ich änderte den Code wie Sie vorgeschlagen haben und behielt meinen Destruktor wie zuvor, aber es stürzt wieder ab ... –

+0

@NoamChai 'delete [] c;' Sie brauchen dies nicht, da Sie alle Objekte in der Schleife bereits gelöscht haben. –

4

Sie versuchen, Zeiger auf und delete Variablen zu dereferenzieren, die automatische Speicherdauer hatten und nicht mehr im Geltungsbereich sind! Hat dich dein Compiler nicht davor gewarnt? Das Verhalten Ihres Programms ist daher undefined.

Sie nur je Paar ein delete[] mit einem new[] und ein delete mit einem new; obwohl Sie die delete (und sogar die new) an eine verwaltete Pointer-Klasse wie std::unique_ptr delegieren können.

Warum refaktorieren Sie nicht auf std::vector<cell> und verwenden Sie Rückgabewertoptimierung?


std::make_unique Verwendung.

+0

... und delegiere das 'neue' an' std :: make_unique' –

+0

@MartinBonner: Danke, das habe ich geklaut. – Bathsheba

3

In cell::createcells Funktion die Variablen lokale und den Gültigkeitsbereich verlassen und werden zerstört, sobald die Funktion zurückkehrt. Diese Objekte sind nicht vorhanden, wenn Sie versuchen, sie zu löschen. Dereferenzieren dieser Zeiger führt zu undefined behavior.

Nicht zu erwähnen, dass Sie nur delete was Sie new. Und da Sie nicht new alles tun delete auf den Zeigern wieder führt zu undefined behavior.

Die einfache Lösung ist ein verwenden vector von Objekte:

std::vector<cell> c; 

Dann fügen Sie einfach acht cell Objekte auf den Vektor:

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

nun der Vektor acht Standard ausgebaute enthalten cell Objekte. Keine Notwendigkeit, etwas im Konstruktor oder Destruktor zu tun. Tatsächlich empfehle ich Ihnen, den Konstruktor und den Destruktor vollständig zu entfernen, entsprechend the rule of zero.