2016-06-20 1 views
1

definierte ich einen Elternteil & ein Kind, wie folgend:Läuft der Speicher beim Aufruf von delete over parent pointer nach reinterpret_cast-in?

struct parent 
{ 
    int i; 

    ~parent() 
    { 
     printf("~parent()\n"); 
    } 
}; 

struct child : public parent 
{ 
    char value[1024*1024]; 

    ~child() 
    { 
     printf("~child()\n"); 
    } 
}; 

int main() 
{ 
    for(int i=0; i < 1000; i++) 
    { 
     char* child_ptr = new char[sizeof(child)](); 
     parent* parent_ptr = reinterpret_cast<parent*>(child_ptr); 
     delete parent_ptr; 
    } 

    return 0; 
} 

oben Code ist legal? Ich meine, dass Speicherlecks? Ich habe mit Windows überprüft, die Speicher scheint nicht durchgesickert zu sein.

+0

haben könnte, was geschrieben steht als Ausgabe beim Ausführen? – thorsan

+0

Windows erhöhen Heap für Appl Bedürfnisse – nikniknik2016

+0

@thorsan '~ parent()' natürlich –

Antwort

3

Genau genommen ist es ein undefiniertes Verhalten: reinterpret_cast ist nicht die richtige für Upcasting. Es funktioniert, weil Darstellungen von child Zeiger und seine base Teile wahrscheinlich gleich sind. Aber bei Vorhandensein von virtuellen Funktionen, mehrfacher oder virtueller Vererbung oder nur einer seltenen Architektur kann Ihr Code fehlschlagen.

Denken Sie daran: reinterpret_cast ist fast immer falsch.

3

Der Code ist ungültig, es gibt keine passende delete[] für die new[]. Sie haben undefiniertes Verhalten und alles kann passieren. Spekulieren, was tatsächlich aufgrund von Beobachtungen geschieht, ist nicht sehr produktiv.

-1

Ich schlage vor, dass Sie Ihre Struktur instanziieren, bevor Sie das Programm ausführen. Bitte instanziieren Sie Ihre Strukturen ... so etwas wie parent par damit die Vorlage (Struktur) zum Leben erwacht. Sie haben die Strukturen gerade deklariert, aber Sie haben keine Objekte von ihnen deklariert. Bis Sie ein Objekt für diese Strukturen deklarieren, sind sie nur Vorlagen!

HINWEIS: Vorlagen in meinem Kommentar beziehen sich nicht auf das templates Konzept in C++. Sie beziehen sich nur auf ein uninstantiiertes Objekt!

+0

Es ist definitiv Speicher zugewiesen, 'new char []' tut das. Sie haben jedoch eine gültige Kritik, der Konstruktor sollte definitiv aufgerufen werden. Bitte beachten Sie, dass 'template' in C++ eine sehr spezifische Bedeutung hat und nicht die von Ihnen verwendete. – MSalters

+0

Um ehrlich zu sein, sehe ich nichts falsches mit dem Schleifenzähler 'i'. Und es ist völlig normal, dass dynamisch erstellte Objekte nicht deklariert werden. (Verwechseln Sie nicht die Deklaration eines Objekts und die Deklaration eines Zeigers) – MSalters

+0

oops! Er hat es als "für (int i = 0 ......)" deklariert. Tut mir leid, mein Fehler, dass ich das nicht bemerkt habe. Ich war verwirrt mit dem in der Struktur. Es macht jedoch keinen Sinn, diese Strukturen zu deklarieren. –

1

Wie andere Antworten angegeben haben, wenn das funktioniert, ist es Zufall. Wenn Sie delete parent_ptr tun, sagen Sie dem Compiler, dass Sie etwas vom Typ parent löschen möchten, aber da der Konstruktor parent nicht zum Erstellen/Zuweisen dieses Speichers verwendet wurde, führt dies zu undefiniertem Verhalten.

Aber ich frage mich, warum Sie das tun möchten. Möchten Sie steuern, wo der Speicher von child zugeordnet ist? Um diese Arbeit zu machen, müssen Sie den Code in ein paar Möglichkeiten ändern:

  • erstellen child durch den Konstruktor
  • Überlastung new zu holen Speicher von wo Sie es wollen (und wenn Sie etwas zu tun, Sonder wie aus einem statischen Puffer holen, überlasten delete richtig zu handhaben löschen)
  • der Destruktor von parent virtuellen so Kind Destruktoren machen sind auch genannt (auch wenn Sie

upcasted) haben Der resultierende Code kann ein bisschen wie folgt aussehen:

struct parent 
{ 
    int i; 

    virtual ~parent() 
    { 
     printf("~parent()\n"); 
    } 
}; 

struct child : public parent 
{ 
    char value[1024*1024]; 

    // you probably also want to overload operator new[] 
    void * operator new (std::size_t size) 
    { 
     return new char[size]; 
    } 

    ~child() 
    { 
     printf("~child()\n"); 
    } 
}; 


int main() 
{ 
    parent * p = new child(); // no need to cast here (obviously) 
    delete p; 

    return 0; 
} 

die druckt:

~child() 
    ~parent() 

Wenn das ist, was Sie nach, Sie auch einen Blick auf What uses are there for "placement new"?

Verwandte Themen