Segmentierungsfehler nach dem Löschen [] des Basisklassenzeigers [duplizieren]

8

Ich habe hier ein Code-Snippet, von dem ich nicht verstehe, warum es in Zeile 22 (delete [] -Anweisung zu einem Segmentierungsfehler kommt). Kannst du mir das bitte erklären?

%Vor%

Seltsamerweise, wenn Klasse B keine Elementvariablen hat (d. h. ich die Zeile "float b;" auskommentiere), läuft der Code einfach gut.

Was ist mein Fehler hier?

    
user3617992 07.01.2018, 13:19
quelle

3 Antworten

11

Einfach gesagt, Sie haben undefiniertes Verhalten. Sie stellen delete[] nicht mit einem Zeiger bereit, den Sie von new[] erhalten haben. Sie können denken, dass Sie das tun, aber damit die Zeiger in der Array-Version identisch sind, muss ihr statischer Typ übereinstimmen. Sie haben den Zeiger in einen Zeiger auf eine Basisklasse konvertiert.

Wenn Sie diese float nicht hinzugefügt haben, behält Ihre Implementierung möglicherweise sizeof(B) == sizeof(A) bei. So machen die Destruktor- und Deallokationsfunktionsaufrufe nichts unmittelbar Schädliches. Aber es ist genauso undefiniert.

    
StoryTeller 07.01.2018, 13:26
quelle
3

delete[] b; wird versuchen, ein Array von A-Objekten und nicht ein Array von B-Objekten zu löschen. Wenn die Klasse B keine Membervariablen hat, dann sind die Größen dieser Arrays identisch, was es wahrscheinlich zulässt, dass Sie dem Geschoss ausweichen können.

Wenn delete aufgerufen wird, wird auf vtable jedes im Array gespeicherten Elements zugegriffen, um einen virtuellen Destruktor aufzurufen. Es wird angenommen, dass die Größe jedes Elements sizeof(A) ist, wenn also sizeof(B) anders ist, wird der Zugriff auf vtable des zweiten Elements mit dem falschen Offset ausgeführt.

    
VTT 07.01.2018 13:25
quelle
1

Wenn Sie mit einem Array einen Polymorphismus wünschen, müssen Sie ein Array von Zeigern für die Basisklasse erstellen.

    
dimm 07.01.2018 14:12
quelle