Löschen von Objekten von unvollständigem Typ
-
29-09-2019 - |
Frage
Dieses hat mich denken:
class X;
void foo(X* p)
{
delete p;
}
Wie können wir delete p
, wenn wir nicht einmal wissen, ob X
sichtbar destructor hat? g ++ 4.5.1 gibt drei Warnungen:
warning: possible problem detected in invocation of delete operator: warning: 'p' has incomplete type warning: forward declaration of 'struct X'
Und dann heißt es:
Hinweis: weder der Destruktor noch der klassenspezifische Operator löschen aufgerufen werden, auch wenn sie deklariert werden, wenn die Klasse definiert ist.
Wow ... sind Compiler erforderlich, um diese Situation wie g zu diagnostizieren ++ tut? Oder ist es nicht definiertes Verhalten?
Lösung
Aus dem Standard [expr.delete]:
Wenn das Objekt, das gelöscht hat unvollständiger Klassentyp an der Stelle der Löschen und die komplette Klasse hat eine nicht-triviale destructor oder Freigabe-Funktion ist das Verhalten nicht definiert.
Es ist UB Also, wenn es nicht-triviale Dinge zu tun, und es ist in Ordnung, wenn es nicht ist. Warnungen sind nicht notwendig für UB.
Andere Tipps
Es ist nicht definiertes Verhalten.
Sie können jedoch die Compiler-Check für unvollständige Typen machen, wie boost:
// verify that types are complete for increased safety
template<class T> inline void checked_delete(T * x)
{
// intentionally complex - simplification causes regressions
typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];
(void) sizeof(type_must_be_complete);
delete x;
}
Die Anwendung sizeof
auf einen unvollständigen Typen sollte einen Fehler auslösen, und ich nehme an, wenn das mit einigen Compiler übergibt, dann eine Reihe von negativer Größe würde einen Fehler auslösen.
Es ist nicht definiertes Verhalten und eine gemeinsame Gotcha wenn das Pimpl Muster zu implementieren. Zum besten meines Wissens gibt es einfach nicht so etwas wie eine Warnung, dass der Compiler auszusenden erforderlich ist. Warnungen sind Wahl; Sie sind da, weil der Compiler Schriftsteller dachte sie nützlich wäre.