Ist es sicher, Speicher aus einem Zeiger eines anderen Typs als aus dem zugewiesenen zuzuordnen?

7

Ich habe eine Frage über die Freigabe von Speicher in C ++:

%Vor%

Wird in diesem Fall der Speicherbereich, auf den p zeigt, komplett gelöscht, selbst nachdem p in einen anderen Typ umgewandelt wurde?

    
LihO 02.01.2013, 21:29
quelle

3 Antworten

14

Das Verhalten ist nicht definiert. In diesem Fall darf das dynamisch zugeordnete Objekt nur über einen Zeiger vom Typ Type1 gelöscht werden.

Erstens verletzen Sie die Aliasregeln, indem Sie den Zeiger verwenden, der von (Type2 *)p im Ausdruck delete erhalten wird. Es gibt eine begrenzte Anzahl von Typen, über die das Objekt, auf das von p verwiesen wird, verwendet werden kann. Die Regeln aus C ++ 03 finden Sie in einer Antwort auf eine andere Frage . Die C ++ 11-Regeln sind ähnlich (die Unterschiede sind für die Antwort auf Ihre Frage nicht relevant).

Selbst wenn das Programm nicht gegen die strengen Aliasing-Regeln verstößt, würde es die Anforderungen des delete -Ausdrucks verletzen. Die Spezifikation besagt (C ++ 11 §5.3.5 [expr.delete] / 3):

  

Wenn der statische Typ des zu löschenden Objekts sich von seinem dynamischen Typ unterscheidet, sollte der statische Typ eine Basisklasse des dynamischen Typs des zu löschenden Objekts und der   Der statische Typ sollte einen virtuellen Destruktor haben oder das Verhalten ist nicht definiert.

In Ihrem Ausdruck delete ist der statische Typ des Objekts Type2 , während der dynamische Typ Type1 ist. Die Typen sind unterschiedlich, aber der statische Typ ist keine Basisklasse des dynamischen Typs.

    
James McNellis 02.01.2013, 21:33
quelle
4

Das wäre eine wirklich schlechte Idee, da Sie den Compiler bitten würden, Typ2 :: ~ Type2 für einen Type1-Zeiger auszuführen, und dieser Destruktor könnte auf das Ende des Objekts verweisen.

In herkömmlichen Umgebungen wäre der eventuelle Speicher frei, weil operator delete free aufruft, was sich nicht interessiert, welchen Typ Sie zur Kompilierzeit aufgerufen haben. In einer nicht so konventionellen Umgebung könnte es jedoch eine Katastrophe sein.

    
bmargulies 02.01.2013 21:34
quelle
0

Obwohl diese Frage von James bereits perfekt beantwortet wurde, möchte ich auf eines hinweisen:

Im richtigen C ++ - Code arbeiten Sie fast nie mit void -Zeigern, was bedeutet, dass Ihr Code wahrscheinlich so aussehen würde:

%Vor%

In diesem Fall, selbst wenn% code_de einen korrekten virtuellen Konstruktor hätte, besteht immer noch ein mögliches undefiniertes Verhalten, wenn BaseType nicht von SubType abgeleitet wird. Common C-Style-Besetzung ist nicht sehr glückliche Wahl hier.

Aber für den Fall, dass Sie BaseType verwenden würden, würde der Compiler das höchstwahrscheinlich nicht zulassen, wenn dynamic_cast nicht auf ein Objekt vom polymorphen Typ zeigt. Und selbst wenn p auf ein Objekt vom polymorphen Typ zeigt, aber p wäre kein Basistyp von BaseType , würde SubType dynamic_cast zurückgeben und Sie könnten diesen Zustand entsprechend behandeln:

%Vor%     
LihO 02.01.2013 22:24
quelle

Tags und Links