2012-04-10 4 views
3

Ich habe die folgende Klasse:Warum kann ich meinen dynamisch zugewiesenen Speicher nicht mit dem Schlüsselwort "delete" zurückfordern?

class Patient { 
public: 
    Patient(int x); 
    ~Patient(); 
private: 
    int* RP; 
}; 

Patient::Patient(int x) { RP = new int [x]; } 
Patient::~Patient() { delete [] RP; } 

ich eine Instanz dieser Klasse auf dem Stapel wie folgt erstellen:

void f() { Patient p(10); } 

Nun, wenn f() zurückkehrt, ich eine „doppelte frei oder Korruption“ erhalten Fehler, der mir signalisiert, dass versucht wird, etwas mehr als einmal zu löschen. Aber ich verstehe nicht, warum das so wäre. Der Platz für das Array wird auf dem Heap erstellt, und nur weil die Funktion, in der der Space zugewiesen wurde, zurückkehrt, würde ich nicht erwarten, dass der Space zurückgewonnen wird.

Ich dachte, dass, wenn ich Speicherplatz auf dem Heap zuweisen (mit dem Schlüsselwort new), dann die einzige Möglichkeit, diesen Speicherplatz zurückzugewinnen ist, verwenden Sie das Schlüsselwort löschen. Hilfe!

Wie gewünscht, hier ist der eigentliche Code (etwas der Kürze halber gekürzt)

Hier ist die vollständige Klassendefinition (split über eine .cpp und .h Datei, aber zusammen dargestellt):

class Patient { 

public: 
    Patient(int numDecisionEpochs); 

    ~Patient(); 

    void recordRP(const int& age, const bool& t); 
    void recordBiopsy(const int& age, const int& result); 
    void recordPSA(const int& age, const double& level); 
    void recordPSA(const int& age); 
private: 
    int* RP; 
    int* Biopsy; 
    double* PSA; 
}; 

Patient::Patient(int numDecisionEpochs) { 
    RP = new int [numDecisionEpochs]; 
    Biopsy = new int [numDecisionEpochs]; 
    PSA = new double [numDecisionEpochs]; 
} 

Patient::~Patient() { 
    delete[] RP; 
} 

void Patient::recordRP(const int& age, const bool& t) { 
    if(t) 
    RP[age-1] = 1; // RP either yes (1) or no (0) 
    else 
    RP[age-1] = 0; 
} 

void Patient::recordBiopsy(const int& age, const int& result) { 
    switch(result) 
    { 
    case 0: 
    case 1: 
    case 2: 
    case 3: 
    case 4: 
     Biopsy[age-1]=result; // only permit results 0,1,2,3,4 
     break; 
    default: 
     cerr << "Invalid biopsy result (" << result << ") at age " << age << "!\n"; 
    } 
} 

void Patient::recordPSA(const int& age, const double& level) { 
    PSA[age-1] = level; // record PSA volume 
} 

void Patient::recordPSA(const int& age) { 
    PSA[age-1] = -1; // symbol for no screening during epoch 
} 

Als nächstes die Funktion, wo die obige Klasse verwendet wird. Die folgende Funktion wird direkt von main() genannt und verabschiedete ein Policy Objekt, das völlig unabhängig und getrennt von der Patient Klasse:

void simulate1(Policy& P) 
{ 
    // ... 
    Patient patient(260); 

    for(int idx=0; idx<(P.size); idx++) 
    { 
     while(state != 9) // while patient not dead 
     { 
       // ... 
       patient.recordPSA(age,PSA); 
       // ... 
       patient.recordPSA(age); 
       // ... 
       patient.recordBiopsy(age,biopsyResult); 
       // ... 
       patient.recordRP(age,true); 
       // ... 
       patient.recordRP(age,false); 
       // ... 

     } // end patient (while loop) 

    } // end sample (for loop) 

} // end function 
+0

Ihr Code läuft gut: http://ideone.com/Gw2QM. Und technisch gesehen ist 'delete' nicht garantiert, irgendeinen Speicherplatz zurückzufordern, es ist möglich, dass Sie eine' neue' und 'delete' Implementierung haben, die nur Speicherseiten zuweisen. –

Antwort

7

Sie verletzen die rule-of-three (oder für C++ 11, die rule-of-five). Sie benötigen einen Kopierkonstruktor und einen Kopierzuweisungsoperator, der eine tiefe Kopie des Zeigers ausführt. Da Sie die Größe des zugewiesenen Arrays nicht verfolgen, ist dies natürlich ohne die Einführung eines zweiten Datenelements nicht möglich.

+0

Es ist auch möglich, dass das Korrigieren des Kopierens am richtigsten wäre, d. H. Hinzufügen von 'privat: Patient (const Patient &);' zur Klassendefinition. Gerade bei Objekten, die manuell mit Zeigern umgehen, kann unbeabsichtigtes Kopieren einfach falsch sein. –

+1

@Steve: Das wahrscheinlichste Szenario, IMO, ist, dass das OP nur 'std :: vector ' anstelle von 'int *' verwenden sollte. ; -] – ildjarn

+0

Was ist "OP", gewöhnliche Person? Wenn ich std :: vector und die "reserve()" -Mitgliedsfunktion zur Vorbelegung von Speicherplatz verwenden, sollte ich erwarten, keinen Geschwindigkeitsunterschied gegenüber der von mir verwendeten Array- und Zeigermethode zu beobachten? (Nehmen Sie an, dass der Code, der das Array oder den Vektor verwendet, der Flaschenhals ist.) – synaptik

2

Dies beantwortet Ihre Frage nicht direkt, sondern auch die Verwendung von std :: vector.

+0

-1 "Diese Antwort ... ist keine Antwort" –

+3

Es ist ein vollkommen gültiger Vorschlag, da der Autor mit C++ nicht sehr erfahren ist. Einer der Fehler beim Lernen von C++ ist es, es wie C zu behandeln und dann zu lernen, wie man Klassen ausführt (so verwaltet man den Speicher selbst für eine Liste von ganzen Zahlen). Dies ist keine direkte Antwort, aber ich denke, in C++ sollte diese Art von Antwort auch gefördert werden. –

+1

Leider habe ich nicht genug Rep, um nur einen Kommentar abzugeben. Ich kann nur antworten. – bluedog

0

Es gibt nichts in den record... Methoden, die Grenzen das Alter überprüft. Wenn also das Alter in Ihrem Beispiel größer als 260 oder kleiner als 0 ist, schreiben Sie über die Grenzen von RP oder Biopsy oder PSA. Das führt direkt zu einem "doppelten freien oder Korruption" -Fehler.

+0

Guter Punkt, aber ich weiß, dass Alter nicht zufällig überschreiten seine Grenzen. Wenn ich beispielsweise die Anweisung delete einfach auskommentiere, wird das Programm ohne Fehler ausgeführt. (Und, ja, ich spreche über die Verwendung genau der gleichen Zufallszahlenstrom.) – synaptik

+0

@Synaptik, nur weil es keinen Fehler wirft, bedeutet nicht, dass es keinen hat. Es bedeutet nur, dass Sie keinen fehlererkennenden Code ausgelöst haben. Verfolgen Sie "numDecisionEpochs" als zusätzliches Mitglied von 'Patient' und sehen Sie, ob Sie jemals älter werden als 'Alter <0 || age> = numDecisionEpochs'. – MSN

+0

du hast recht! Ich hätte das sagen sollen, anstatt frei von Fehlern zu sein, wirft es zumindest nicht den doppelten freien Fehler. Ich werde das nochmal überprüfen, danke für den Vorschlag. – synaptik

Verwandte Themen