Bei Anrufen über Variable löschen auf dem Stapel reserviert
-
22-07-2019 - |
Frage
Das Ignorieren Programmierstil und Design, ist es „sicher“ auf eine Variable auf dem Stapel zugeordnet löschen anrufen?
Zum Beispiel:
int nAmount;
delete &nAmount;
oder
class sample
{
public:
sample();
~sample() { delete &nAmount;}
int nAmount;
}
Lösung
No , ist es nicht Safe delete
auf einem Stapel zugewiesene Variable zu nennen. Sie sollten nur delete
auf Dinge von new
erstellt nennen.
- Für jede
malloc
odercalloc
, sollte es genau einfree
. - Für jede
new
sollte es genau eindelete
. - Für jede
new[]
sollte es genau eindelete[]
. - Für jeden Stapel Zuteilung sollte es keine explizite Freigabe oder Löschung sein. Der Destruktor wird automatisch aufgerufen, wo anwendbar.
In der Regel können Sie nicht davon mischen und anzupassen, z.B. kein free
-ing oder delete[]
-ing ein new
Objekt. so ergibt sich ein undefiniertes Verhalten zu tun.
Andere Tipps
Nun, versuchen sie es:
jeremy@jeremy-desktop:~$ echo 'main() { int a; delete &a; }' > test.cpp
jeremy@jeremy-desktop:~$ g++ -o test test.cpp
jeremy@jeremy-desktop:~$ ./test
Segmentation fault
So offensichtlich ist es überhaupt nicht sicher.
Beachten Sie, dass, wenn Sie einen Speicherblock mit neuen (oder malloc was das betrifft) zuzuordnen, zugeordnet der tatsächliche Speicherblock wird größer sein als das, was Sie gefragt. Der Speicherblock wird auch einige Buchhaltungsinformationen enthalten, so dass, wenn Sie den Block freizugeben, kann es leicht wieder in den freien Pool gestellt werden und möglicherweise mit benachbarten freien Blöcken verschmolzen werden.
Wenn Sie versuchen, eine Erinnerung zu befreien, die Sie nicht von neuen erhalten haben, dass Buchhaltungsinformationen werden nicht dort sein, aber das System handeln, wie es ist, und die Ergebnisse werden unberechenbar (in der Regel schlecht) sein.
Ja, es ist nicht definiertes Verhalten: passing etwas delete
, die nicht aus new
gekommen ist UB:
C ++ Standard Abschnitt 3.7.3.2.3: Der Wert des ersten Arguments einen der Thea Deallokation Funktionen in der Standardbibliothek bereitgestellt geliefert wird, kann ein
null
Zeigerwert sein; wenn ja, und wenn die Aufhebung der Zuordnung einer Funktion in der Standardbibliothek geliefert ist, hat der Aufruf an die Aufhebung der Zuordnung Funktion keine Auswirkung. Andernfalls wird der Wert zuzuführendenoperator delete(void*)
in der Standardbibliothek einen des Wertes von einem frühen Aufruf von entwederoperator new(std::size_t)
operator new(std::size_t, const std::nothrow_t&)
oder in der Standardbibliothek zurückgeführt werden.
Die Folgen der undefinierten Verhalten sind, na ja, nicht definiert. „Nichts passiert“ ist als gültige Folge als irgendetwas anderes. Allerdings ist es in der Regel „nichts sofort geschieht“. Einen ungültigen Speicherblock freigibt, in späteren Aufrufen schwerwiegende Folgen auf das allocator hat
Nach einem wenig mit g ++ 4.4 in Windows zu spielen, habe ich sehr interessante Ergebnisse:
-
Aufruf auf einem Stapel Variable löschen scheint nicht, etwas zu tun. Keine Fehler werfen, aber ich kann die Variable ohne Probleme nach dem Löschen zugreifen zu können.
-
eine Klasse mit einer Methode mit
delete this
Nachdem erfolgreich löscht das Objekt, wenn es in dem Heap zugeordnet wird, aber nicht, wenn es in dem Stapel zugeordnet ist (wenn es in dem Stapel ist, passiert nichts).
Niemand kann wissen, was passiert. Das ruft nicht definiertes Verhalten, so buchstäblich alles passieren kann. Sie dies nicht tun.
Nein, Speicher mit neuen zugewiesen sollte löschen Verwendung gelöscht Operator und dass zugewiesen mit malloc sollte mit dem kostenlosen gelöscht werden. Und keine Notwendigkeit, die Variable freigeben, die auf Stapel zugeordnet sind.
Ein Engel verliert seine Flügel ... Sie nur delete
auf einem Zeiger zugewiesen mit new
aufrufen können, sonst Sie nicht definiertes Verhalten zu bekommen.
Hier wird der Speicher mit Stapeln so dass keine Notwendigkeit zugeordnet es exernally zu löschen, aber wenn Sie dynamisch allcoted
wie int * a = new int ()
, dann müssen Sie ein tun löschen und nicht löschen & a (a selbst ist ein Zeiger), da der Speicher aus freien Speicher zugeordnet ist.
Sie bereits beantwortet die Frage selbst. delete
darf nur für Zeiger verwendet werden optained durch new
. Etwas anderes zu tun ist schlicht und einfach nicht definiertes Verhalten.
Deshalb gibt es wirklich keine zu sagen, was passiert, etwas von dem Code adaequat zu Löschen einer Festplatte durch Absturz ist ein gültiges Ergebnis, dies zu tun. Also bitte dies nie tun .
Es ist UB, weil Sie nicht auf ein Element löschen aufrufen müssen, die mit neuen nicht dynamisch zugeordnet. Es ist so einfach.