Wie hier hier gezeigt, kann man mit dynamic_cast
einen gelöschten Zeiger erkennen:
die Ausgabe:
%Vor%Es wird erklärt, dass das Löschen der vtable erkannt wurde.
Aber ich frage mich, wie ist das möglich, da wir den freigegebenen Speicher nicht überschreiben?
Und ist diese Lösung vollständig tragbar?
Danke
Zunächst einmal führt der Versuch, ein gelöschtes Objekt in irgendeiner Form zu verwenden, zu undefiniertem Verhalten: was auch immer Sie sehen, kann passieren!
Der Grund für das beobachtete Verhalten ist einfach, dass ein Objekt während der Zerstörung seinen Typ ändert: Von einem Objekt des konkreten Typs wird es durch alle Arten in der Hierarchie geändert. An jedem Punkt ändern sich die virtuellen Funktionen und die vtable (oder ähnlich) wird ersetzt. Der dynamic_cast<...>()
erkennt diese Änderung in den Bytes, die am Ort des Objekts gespeichert sind, einfach.
Falls Sie gerne zeigen möchten, dass diese Technik nicht zuverlässig funktioniert, können Sie den Inhalt des gelöschten Speichers auf ein zufälliges Bitmuster oder das Bitmuster eines Objekts des am weitesten abgeleiteten Typs setzen: ein zufälliges Bitmuster führt wahrscheinlich zu einem Absturz und memcpy()
behauptet wahrscheinlich, dass das Objekt noch Leben ist. Natürlich, da es undefiniertes Verhalten ist, kann alles passieren.
Ein relevanter Abschnitt zu diesem 3.8 [basic.life] Absatz 5:
Bevor die Lebensdauer eines Objekts begonnen hat, aber nachdem der Speicher, den das Objekt belegen soll, zugewiesen wurde oder nachdem die Lebensdauer eines Objekts beendet wurde und bevor der Speicher, den das Objekt belegt hat, wiederverwendet oder freigegeben wird, alle Zeiger, die sich beziehen zu dem Speicherort, an dem das Objekt sein wird oder war, kann verwendet werden, aber nur in begrenzter Weise. Für ein Objekt im Aufbau oder Zerstörung, siehe 12.7. Andernfalls verweist ein solcher Zeiger auf den zugeordneten Speicher (3.7.4.2) und verwendet den Zeiger, als ob der Zeiger vom Typ
void*
wäre. ist klar definiert. Die Indirektion durch einen solchen Zeiger ist erlaubt, aber der resultierende L-Wert kann nur in begrenzter Weise verwendet werden, wie nachstehend beschrieben. Das Programm hat ein undefiniertes Verhalten, wenn:
- ...
- Der Zeiger wird als Operand eines dynamic_cast (5.2.7) verwendet. ...
Seltsamerweise verwendet das Beispiel für den letzten Punkt in dynamic_cast
nicht dynamic_cast
.
Natürlich wird das Objekt wahrscheinlich auch freigegeben, in welchem Fall die obigen Garantien nicht einmal zutreffen.
Tags und Links c++ vtable dynamic-cast