Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

Faule Socke

Community-Fossil

  • »Faule Socke« ist der Autor dieses Themas

Beiträge: 1 915

Wohnort: Schreibtischstuhl

  • Private Nachricht senden

1

28.02.2009, 14:23

[Erledigt] Heap Corruption

Hi,

ich arbeite ja zur Zeit an nem Spiel (i-wann werd ich es auch hier ankündigen). So neulich hab ich was geändert (wer hätte es gedacht) und seit dem bekomme ich beim Beenden folgende Fehlermeldung:


(Link)


Natürlich hab ich schon debugt. Zuerst aber noch ein paar Infos: Ich hab mir eine kleine Memory-Leak-Detection geschrieben (also new + delete überladen), hier mal der Relevante Teil:

C-/C++-Quelltext

1
2
3
4
5
inline void operator delete(void *p)
{
    RemoveTrack(unsigned long(p));
    free(p);
}


Die Funktion RemoveTrack entfernt einfach nur den Eintrag aus einer Liste. Wenn ich in Der Fehlermeldung auf "Wiederholen" klicke zeigt mir der Debugger die Zeile mit dem "free(p)" an. Wenn ich ein bisschen durch den Call-Stack gehe, um rauszufinden, welcher Speicher freigegeben werden sollte stelle ich fest, dass es Speicher von einer Klasse aufm Heap ist. Das ist logisch, denn an genau dieser Klasse habe ich änderungen vorgenommen. Ich weiß leider nicht mehr was ich alles geändert habe und ich kann es auch leider nicht mehr rückgängig machen (also letzte Revision vom svn herstellen), da ich schon viel zu viel geändert habe und das ein enormer Arbeitsverlust wäre.

Ein paar Fragen: Wie entsteht so ein Fehler? Braucht ihr eventuell noch ein bisschen mehr code? (Ich kann leider nicht viel rausgeben, da ich den Quellcode von diesem Spiel erstmal nicht freigeben werde). Braucht ihr noch Infos?

Alle Vorschläge sind willkommen, ich probier jetzt schon seit Tagen das Problem zu lösen.

Socke

WhiteMike

Alter Hase

Beiträge: 507

Wohnort: Ulm

Beruf: Schüler

  • Private Nachricht senden

2

28.02.2009, 14:36

Wenn du den delete-Operator überlädst, kannst du auch prüfen, ob p != NULL. ;-)

Und warum verwendest du nicht wieder das standardmäßige delete, wenn du die Einträge aktualisiert hast?

C-/C++-Quelltext

1
2
3
// ...

::operator delete (p);
}


Ich weiß nicht, ob es dir hilft, aber ggf. könntest du die Größe der zu löschenden Instanz überprüfen.

C-/C++-Quelltext

1
2
3
4
5
6
7
8
::operator delete(void* p, std::size_t size) throw ()
{
    if (p == NULL) return;
    if (size != sizeof(*p))
        // Error!

    // ...

}
}


Aber es ist fraglich, ob das alles hilfreich ist. Wenn du was an der Klasse verändert hast, liegt der Fehler vielleicht dort.
Musst du vielleicht etwas vererbungsspezifisches beachten?

Mit freundlichen Grüßen,
WhiteMike

Gotbread

Alter Hase

Beiträge: 421

Beruf: Student (Etechnik) + Hiwi

  • Private Nachricht senden

3

28.02.2009, 14:53

Zitat von »"WhiteMike"«


C-/C++-Quelltext

1
2
3
4
5
6
7
8
::operator delete(void* p, std::size_t size) throw ()
{
    if (p == NULL) return;
    if (size != sizeof(*p))
        // Error!

    // ...

}
}



welche größe hat den void ;)

ich vermute eher dass du 2mal den selben Bereich freigibst,
oder einen Bereich der garnicht reserviert wurde.
überpüfe das doch mal in der Liste beim entfernen des Eintrags,
wenn sich kein Eintrag in der Liste befindet hast du den Fehler.
Mfg Goti
www.gotbread.bplaced.net
viele tolle spiele kostenlos, viele hardware-basteleien :)

"Es ist nicht undicht, es läuft über" - Homer Simpson

WhiteMike

Alter Hase

Beiträge: 507

Wohnort: Ulm

Beruf: Schüler

  • Private Nachricht senden

4

28.02.2009, 15:12

Das kommt davon, wenn man versucht Lösungen von klasseninternen delete-Überladungen auf das aktuelle Problem zu portieren. :roll:

Mit freundlichen Grüßen,
WhiteMike

Faule Socke

Community-Fossil

  • »Faule Socke« ist der Autor dieses Themas

Beiträge: 1 915

Wohnort: Schreibtischstuhl

  • Private Nachricht senden

5

28.02.2009, 16:22

Also der Pointer ist nicht 0 das sagt zumindest der Debugger. Die größe kann ich leider nicht prüfen, ich speicher sie zwar auch in meiner Liste nur ist die Frage, ob ich den delete Operator so überladen kann, dass er auch noch die größe übernimmt? Dass ich free benutze hat schon seinen Grund, denn ich benutze ja auch malloc um den Speicher zu reservieren und die Standard new + delete zu verwenden macht dann i-wie keinen Sinn mehr.
Ob ich vererbungsspezifische Dinge beachten muss? Eigentlich nicht, die Erzeugte Instanz ist von einer Interfaceklasse mit lauter pure-virtual Methoden abgeleitet. Diese wiederum ist von einer Reference counter Klasse abgeleitet, die nur die Methoden AddRef und Release implementiert (virtual) und halt den Ref. counter im protected Bereich.

Sonst noch Ideen?

Socke

Nox

Supermoderator

Beiträge: 5 272

Beruf: Student

  • Private Nachricht senden

6

28.02.2009, 16:51

Zitat

Ich weiß leider nicht mehr was ich alles geändert habe und ich kann es auch leider nicht mehr rückgängig machen (also letzte Revision vom svn herstellen),

wozu gibt es diff? Vorallem kannst du über dein System doch feststellen, um was für ein Objekt es sich überhaupt handelt, welches den Fehler verursacht. Wahrscheinlich hast du einfach ein Objekt gelöscht, aber nicht alle Zeiger dabei erwischt (ggf. _ptr aus z.b. boost nutzen?).
PRO Lernkurs "Wie benutze ich eine Doku richtig"!
CONTRA lasst mal die anderen machen!
networklibbenc - Netzwerklibs im Vergleich | syncsys - Netzwerk lib (MMO-ready) | Schleichfahrt Remake | Firegalaxy | Sammelsurium rund um FPGA&Co.

Mordrak

1x Contest-Sieger

Beiträge: 121

Wohnort: München

Beruf: Junior IT Consultant

  • Private Nachricht senden

7

28.02.2009, 17:01

Re: Heap Corruption

Zitat von »"Faule Socke"«

Ein paar Fragen: Wie entsteht so ein Fehler?


Viele Corruption-Probleme entstehen in erster Linie einmal nicht dort, wo man es erwarten wuerde. Meist irgendwo ganz anderst...

Gruesse,
Mordrak, der sich an eine muehsam zu debuggende Heapcorruption erinnert, die immer erst ca. 5-10 Minuten spaeter und auch nur bei sehr speziellen Eingabedaten zu einem Absturz gefuehrt hat...
What's yellow and equivalent to the axiom of choice? The Lemmon of Zorn!

S.Seegel

2x Contest-Sieger

  • Private Nachricht senden

8

28.02.2009, 17:07

Wie dir die Fehlermeldung schon sagt, schreibt dein Programm über den auf dem Heap reservierten Speicherbereich hinaus.
Ein solcher Fehler wird zwar erst beim Aufruf von delete bzw. free bemerkt (da zu diesem Zeitpunkt bei einem Debug-Build die Heap-Datenstrukturen überprüft werden), der Fehler kann aber beliebig weit davor passiert sein.

Eine Möglichkeit ist, dass du einen bereits wieder freigegebenen Bereich weiterverwendest. Diesen Fall kann deine RemoveTrack() Funktion erkennen: wenn die aus der Liste zu löschende Adresse gar nicht in der Liste steht.

Eine andere Möglichkeit ist der Fall, dass du an irgend einer Stelle zu wenig Speicher reservierst. Der Klassiker wäre ein off-by-one Fehler bei der Nutzung eines Arrays (x Elemente reserviert und dann auf Index x zugreifen).
Aber auch wenn du für ein Objekt zu wenig Speicher reservierst, wird durch regulären Zugriff auf dessen Member über den reservierten Speicherbereich hinaus zugegriffen.

Faule Socke

Community-Fossil

  • »Faule Socke« ist der Autor dieses Themas

Beiträge: 1 915

Wohnort: Schreibtischstuhl

  • Private Nachricht senden

9

28.02.2009, 17:12

@Nox: Ja ich weiß ja welches Objekt gelöscht wird ich weiß welche Klasse es ist und dass es eigentlich nur eine Instanz davon gibt.

Ich beschreibe mal den groben Ablauf:
Mein Objektmanager hat einen Zeiger auf den ModManager (das ist die Klasse die Probleme macht). Er Ruft nun Release auf. Da Der Referenzzähler auf 1 steht löscht sich das Objekt selbst mit delete. Nun wird ja bekanntlich der Destruktor aufgerufen. Er löscht noch ein paar andere Objekte die Zeiger auf den ModManager haben. Dann kommt meine Memory-Leak-Detection zum Einsatz, denn der Speicher soll ja Freigegeben werden. Der Eintrag wird aus der Liste entfernt, dann kommt der Aufruf der free Funktion und dann kommt meine Meldung.

Ich probier grade mal, ob es eventuell Probleme mit boost gibt, das war nämlich eine der "größeren" Änderungen die ich gemacht habe, boost integriert (davor wurde es nicht benötigt).

Socke

Faule Socke

Community-Fossil

  • »Faule Socke« ist der Autor dieses Themas

Beiträge: 1 915

Wohnort: Schreibtischstuhl

  • Private Nachricht senden

10

28.02.2009, 17:56

Hey cool, Problem gelöst. Was genau ich gemacht habe was ich auch nicht, ich hab jedenfalls nachdem ich Boost wieder rausgenommen hab und das auch nicht geholfen hab ich es wieder eingebaut. Dann hab ich noch 2 unordentliche c'tors (Vom Objektmanager und vom Modmanager) neu geschrieben und eine Lade-Methode. Jetzt geht es wieder und ich kann endlich weiter Programmieren (ich hab über ne Woche an dem Fehler gesucht). :D :D

Danke für eure Hilfen und Vorschläge!

Socke

Werbeanzeige