Frage

Ich habe eine einfache geschrieben, arbeiten tetris Spiel mit jedem Block als eine Instanz einer Klasse single.

class SingleBlock
{
    public:
    SingleBlock(int, int);
    ~SingleBlock();

    int x;
    int y;
    SingleBlock *next;
};

class MultiBlock
{
    public:
    MultiBlock(int, int);

    SingleBlock *c, *d, *e, *f;
};

SingleBlock::SingleBlock(int a, int b)
{
    x = a;
    y = b;
}

SingleBlock::~SingleBlock()
{
    x = 222;
}

MultiBlock::MultiBlock(int a, int b)
{
    c = new SingleBlock (a,b);
    d = c->next = new SingleBlock (a+10,b);
    e = d->next = new SingleBlock (a+20,b);
    f = e->next = new SingleBlock (a+30,b);
}

Ich habe eine Funktion, dass Scans für eine komplette Linie, und verläuft durch die verkettete Liste von Blöcken der entsprechend diejenigen zu löschen und Neuzuordnung. -> nächsten Zeigers

SingleBlock *deleteBlock;
SingleBlock *tempBlock;

tempBlock = deleteBlock->next;
delete deleteBlock;

Das Spiel funktioniert, Blöcke richtig und alle Funktion gelöscht, wie es soll. Allerdings kann ich bei der Inspektion immer noch Zugriff auf Zufallsbits von gelöschten Daten.

Wenn ich jede der gelöschten singleblocks printf „x“ Werte nach deren Löschung, kehren einige von ihnen zufällig Müll (Bestätigung der Löschung) und einige von ihnen 222 zurückkehren, mir zu sagen, auch wenn die destructor die Daten genannt wurde, war nicht tatsächlich aus dem Heap gelöscht. Viele identischen Studien zeigen, es ist immer die gleichen spezifischen Blöcke, die nicht richtig gelöscht werden.

Die Ergebnisse:

Existing Blocks:
Block: 00E927A8
Block: 00E94290
Block: 00E942B0
Block: 00E942D0
Block: 00E942F0
Block: 00E94500
Block: 00E94520
Block: 00E94540
Block: 00E94560
Block: 00E945B0
Block: 00E945D0
Block: 00E945F0
Block: 00E94610
Block: 00E94660
Block: 00E94680
Block: 00E946A0

Deleting Blocks:
Deleting ... 00E942B0, X = 15288000
Deleting ... 00E942D0, X = 15286960
Deleting ... 00E94520, X = 15286992
Deleting ... 00E94540, X = 15270296
Deleting ... 00E94560, X = 222
Deleting ... 00E945D0, X = 15270296
Deleting ... 00E945F0, X = 222
Deleting ... 00E94610, X = 222
Deleting ... 00E94660, X = 15270296
Deleting ... 00E94680, X = 222

Ist in der Lage, den Zugriff auf Daten aus dem Jenseits zu erwarten?

Sorry, wenn dies ist etwas langatmig.

War es hilfreich?

Lösung

  

Ist in der Lage, den Zugriff auf Daten aus dem Jenseits zu erwarten?

Dies ist als nicht definiertes Verhalten technisch bekannt. Seien Sie nicht überrascht, wenn es Ihnen eine Dose Bier bietet auch nicht.

Andere Tipps

  

Ist in der Lage, den Zugriff auf Daten aus dem Jenseits zu erwarten?

In den meisten Fällen ja. löschen Aufruf Null den Speicher nicht.

Beachten Sie, dass das Verhalten nicht definiert ist. Die Verwendung bestimmter Compiler kann der Speicher auf Null gesetzt werden. Wenn Sie löschen rufen, was passiert ist, dass der Speicher als verfügbar gekennzeichnet ist, so dass das nächste Mal jemand tut neue , kann der Speicher verwendet werden.

Wenn man darüber nachdenkt, ist es logisch - wenn Sie den Compiler sagen, dass Sie nicht mehr interessiert im Speicher (mit löschen ), warum sollte der Computer verbringen Zeit auf sie Nullstellen

Es ist, was C ++ nicht definiertes Verhalten nennt - Sie könnten in der Lage sein, die Daten zugreifen zu können, vielleicht nicht. In jedem Fall ist es die falsche Sache zu tun.

Löschen nicht löschen nichts - es Markierungen nur den Speicher als „frei für die Wiederverwendung zu sein“. Bis einige andere Amtsruf Reserven und Füllungen, dass der Raum es werden die alten Daten. Jedoch auf, dass unter Berufung ist eine große no-no, im Grunde, wenn Sie es löschen etwas vergessen.

Eine der Praktiken in diesem Zusammenhang, die oft in Bibliotheken auftreten, ist eine Löschfunktion:

template< class T > void Delete( T*& pointer )
{
    delete pointer;
    pointer = NULL;
}

Dies verhindert, dass uns versehentlich Zugriff auf ungültige Speicher.

Beachten Sie, dass es vollkommen in Ordnung ist, um den Anruf delete NULL;.

Heap-Speicher ist wie ein Haufen von tafeln. Stellen Sie sich vor Sie sind ein Lehrer. Während Sie Ihre Klasse sind Lehre gehört die Tafel zu Ihnen, und Sie können tun, was Sie damit tun wollen. Sie können sich darauf kritzeln und überschreiben Sachen, wie Sie wollen.

Wenn die Klasse ist vorbei und Sie sind über den Raum zu verlassen, gibt es keine Richtlinie, die Sie erfordert die Tafel löschen - Sie einfach die Tafel Hand von zum nächsten Lehrer, der generell in der Lage sein wird, um zu sehen, was Sie geschrieben nach unten.

Das System löscht nicht den Speicher, wenn Sie es über delete() freigeben. Die Inhalte sind daher nach wie vor zugänglich, bis der Speicher für die Wiederverwendung zugewiesen wird und überschrieben.

löschen Speicherfreigabe der Speicher, aber nicht verändert es nicht oder es Null aus. Dennoch sollten Sie nicht darauf zugreifen deallokierten Speicher.

Nach dem Löschen eines Objekts ist es nicht definiert, was den Inhalt des Speichers geschehen wird, dass es besetzt. Es bedeutet, dass die Speicher frei wiederverwendet werden, aber die Umsetzung muss nicht um die Daten zu überschreiben, die es ursprünglich war, und es muss nicht sofort die Erinnerung wiederverwendet werden.

Sie sollen nicht auf den Speicher zugreifen, nachdem das Objekt verschwunden ist, aber es sollte nicht surpising wird, dass einige Daten bleiben in Takt gibt.

Es wird nicht Null / Wechselspeicher nur noch ... aber irgendwann wird der Teppich geht unter den Füßen gezogen werden.

Nein, es ist sicherlich nicht vorhersehbar. Es hängt davon ab, wie schnell die Speicherzuordnung / Deallokation aufgewühlt wird

Ja, es kann manchmal zu erwarten. Während new Reserven Platz für Daten, entkräftet delete einfach einen Zeiger mit new erstellt, so dass Daten an den zuvor reservierten Stellen geschrieben werden; es gibt nicht unbedingt die Daten löschen. Sie sollten jedoch nicht auf dieses Verhalten verlassen, weil die Daten an den Stellen jederzeit ändern könnte, möglicherweise Ihr Programm misbehave verursacht. Aus diesem Grunde, nachdem Sie delete auf einem Zeiger (oder delete[] auf einem Array mit new[] zugeordnet) verwenden, können Sie NULL, um es so, dass man nicht manipulations mit einem ungültigen Zeiger zuweisen sollten, vorausgesetzt, Sie Speicher nicht zuweisen werden mit new oder new[] vor, dass die Zeiger wieder verwenden.

Es wird nicht definiertes Verhalten und löschen Speicherfreigabe Speicher führen, es es nicht neu initialisiert werden mit Null.

Wenn Sie es Null aus dann tun machen wollen:

SingleBlock::~SingleBlock()

{    x = y = 0 ; }

Es ist zwar möglich, dass Ihre Laufzeit dieser Fehler nicht melden, indem eine richtige Fehlerprüfung Laufzeit wie Valgrind werden Sie auf die Verwendung von Speichern aufmerksam, nachdem er befreit wurde.

Ich empfehle, dass, wenn Sie schreiben Code mit new / delete und rohen Zeigern (statt std::make_shared() und ähnlichen), dass Sie Ihre Unit-Tests unter Valgrind ausüben zumindest eine Chance haben, solche Fehler Spek.

Nun, ich habe auch schon eine ganze Weile darüber schon gefragt, und ich habe versucht, einige Tests besser zu verstehen, zu laufen, was unter der Haube geht. Die Standard-Antwort ist, dass nach dem Aufruf löscht Sie sollten nicht alles gut aus Zugriff auf diesen Speicher vor Ort erwarten. Dies ist jedoch nicht genug, um mich zu sein schien. Was ist es wirklich geschieht beim Aufruf von delete (ptr) ? Hier ist, was ich gefunden habe. Ich bin mit g ++ auf Ubuntu 16.04, so dass dies eine Rolle in den Ergebnissen spielen kann.

Was ich zunächst erwartet, wenn der Löschoperator war, dass die freigegebenen Speicher in anderen Prozessen handed zurück an das System für den Einsatz sein würde. Lassen Sie mich sagen, Geschieht dies nicht unter einer der Umstände, die ich versucht habe.

Speicher freigegeben mit Löschen scheint es immer noch es zuerst mit neuen zugewiesen das Programm zugeordnet werden. Ich habe versucht, und es gibt keine Speichernutzung Abnahme nach dem Aufruf von löschen . Ich hatte eine Software, die allcated um 30MB Listen durch neue Anrufe und sie dann mit anschließender Freigabe löschen Anrufe. Was passiert ist, ist, dass bei der System-Monitor zu suchen, während das Programm ausgeführt wurde, auch einen langen Schlaf nach dem Löschen Anrufe, Speicherverbrauch meine das Programm das gleiche war. Keine Abnahme! Dies bedeutet, dass löschen entbindet Speicher an das System.

In der Tat, es sieht aus wie Speicher von einem Programm zugeordnet ist sein für immer! Jedoch ist der Punkt, dass, wenn freigegeben, kann der Speicher wieder durch das gleiche Programm verwendet werden, ohne weitere zuzuordnen ist. Ich habe versucht, 15MB zuzuteilen, befreien sie, und dann eine weitere 15MB von Daten nach Zuteilung und das Programm nie 30MB verwendet. Der Systemmonitor zeigte, dass es immer um 15MB. Was ich in Bezug auf den vorherigen Test war getan, nur um die Reihenfolge zu ändern, in den Dinge geschehen: Halb Zuteilung, halb Deallokation, andere Hälfte der Zuteilung.

So offenbar Speicher durch ein Programm verwendet wird, kann erhöhen, aber schrumpfen nie . Ich dachte, dass vielleicht würde Speicher wirklich für andere Prozesse in kritischen Situationen freigesetzt werden, wie zum Beispiel, wenn es keine mehr Speicher zur Verfügung. Nach allem, was Sinn würde es macht ein Programm hält seinen eigenen Speicher zu lassen, für immer, wenn andere Prozesse für sich fragen? Also habe ich die 30MB wieder zugeordnet und , während sie das Aufheben von Zuweisungen Ich betreibe ein memtester mit wie viel physischer Speicher ich konnte. Ich erwartete, meine Software Hand aus seinem Speicher memtester zu sehen. Aber wissen Sie es, es ist nicht geschehen!

Ich habe einen kurzen Screencasts gemacht, dass zeigt das Ding in Aktion:

100% ehrlich zu sein, es war in eine Situation, etwas passiert ist. Als ich versuchte, memtester mit mehr als dem verfügbaren physischen Speicher in der Mitte des Deallokation Prozesses meines Programms, das durch mein Programm verwendeten Speicher sanken auf rund 3 MB. Der memtester Prozess wurde automatisch obwohl getötet, und das, was passiert ist, war noch mehr überrascht! Der Speicherverbrauch meines Programms erhöht mit jedem Lösch Anruf! Es war so, als ob Ubuntu seinen ganz zurück Speicher nach dem memtester Vorfall wurde gestellt wird.

  

Entnommen    http://www.thecrowned.org/c-delete-operator- wirklich-frees-Speicher

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top