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

eXpl0it3r

Treue Seele

Beiträge: 386

Wohnort: Schweiz

Beruf: Professional Software Engineer

  • Private Nachricht senden

11

25.12.2012, 16:08

Ich kenne mich zwar nicht wirklich aus mit SDL, aber so wie es aussieht geschiet wirklich, das was ich vorhin gesagt habe.
In CSelectionScreen erstellst du eine Instanz eines CSprites und gibst dem Pointer m_pSpriteBisasam die Adresse, dann pushed du das dereferenzierte Sprite in die Liste, wobei STL hier dann natürlich eine Kopie erstellt, ich bin mir hier natürlich nicht sicher ob da alles korrekt kopiert wird, aber wenn schon, dann hast du jetzt zwei Klassen, welche intern auf die gleiche SDL_Surface zeigen. Wenn nun Instanz1 geschlöscht wird, dann ruft die SDL_FREESURFACE auf mit der Adresse und setzt den Member Pointer auf NULL, danach wird Instanz2 gelöscht, welche immer noch einen Member Pointer auf das nicht mehr existierende Bild hat und übergibt dann diese falsche Adresse ebenfalls SDL_FREESURFACE was natürlich zu einem crash führt.
Also noch einmal, du hast zwei Instanzen, welche jeweils einen verschiedenen Pointer haben, welche beide auf das selbe Bild zeigen und du versuchst dann das Bild zweimal zu löschen, was zum Crash führt.
IMHO sollten die Bilder nicht von der Sprite Klasse selbst gemanaget werden, sondern separat und du solltest das Kopieren von CSprite entweder verbieten oder eben richtig implementieren.

Ich persönlich würde dir ja jetzt SFML empfehlen, da das dort um einiges einfacher und schöner gelöst ist... ;)

Beim nächsten Projekt werde ich darauf achten das C vor dem Klassennamen wegzulassen, nur wäre es zu umständlich es in 16hpps und cpps zu ändern.
Es gibt ja auch suchen & ersetzten Funktionen, welche über alle Files eines Projekts laufen können... :P
Blog: https://dev.my-gate.net/
—————————————————————————
SFML: https://www.sfml-dev.org/
Thor: http://www.bromeon.ch/libraries/thor/
SFGUI: https://github.com/TankOs/SFGUI/

12

25.12.2012, 16:12

Du verletzt die "Rule of three"
http://en.wikipedia.org/wiki/Rule_of_thr…_programming%29

Schematischer Ablauf was passiert, und wo das Problem ist:
- Du erstellst ein Sprite. m_pImage ist uninitialisiert, und wird vom ctor nichteinmal auf 0 gesetzt (potentiell gefährlich)
- als nächstes Lädst du das Sprite, ab jetzt ist alles wunderbar
- du kopierst das Sprite in die Liste. Du hast keinen Kopierkonstruktor, also generiert der Compiler einen für dich, der eine flache Kopie erzeugt
- jetzt hast du 2 Objekte, deren p_Image-Zeiger auf den selben Speicherbereich zeigen
- sobald du eines von ihnen löschst, wird dessen Destruktor aufgerufen und der Zeiger ist ungültig. Weil das andere Objekt den selben Zeiger hatte, ist sein Speicher nun auch ungültig
- sobald du jetzt das zweite Objekt löschst oder zum Rendern benutzt, wird auf ungültigen Speicher zugegriffen, das kann nur schief gehen

Du hast also eine Klasse, die man nicht korrekt kopieren kann und tust es trotzdem. Jede Klasse, von der du nicht sicher bist, ob man sie korrekt kopieren kann, sollte das Kopieren vollständig verbieten, zum Beispiel mittels:
http://www.boost.org/doc/libs/1_52_0/lib…ass_noncopyable
Mehr Infos zum Thema:
http://en.wikibooks.org/wiki/More_C%2B%2…-copyable_Mixin

Jetzt kannst du die Klasse nicht mehr in die Liste packen, du kannst aber sehr wohl std::unique_ptr's in die Liste packen. Oder du übst Kopierkonstruktor schreiben und machst diene Spriteklasse kopierbar.

Wenn du noch nicht dazu bereit bist, dich in derart fortschrittliche Themen einzuarbeiten, ist die wohl einfachste Lösung, Zeiger auf dynamisch allokierte Objekte (mittels new) in die Liste zu packen, und am Ende alle Objekte von Hand zu löschen. Dadurch umgehst du auch das Kopieren der Objekte. Beispiel:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
list<CSprite*> SpriteList;
SpriteList.push_back(new CSprite("meinTollesBild.bmp");


//und wenn du die Spriteliste löschen willst:
for(list<CSprite*>::iterator it=SpriteList.begin(); it!=SpriteList.end(); ++it)
{
  delete *it;
}
SpriteList.clear();
Lieber dumm fragen, als dumm bleiben!

13

25.12.2012, 16:37

Danke für die tollen Tipps, wusste garnicht das es eine suchen und ersetzten Funktion gibt. Ich werde mich mal in die Themen einlesen wird allerdings ein wenig dauern, da englisch sich immer ein wenig schwieriger liest^^.
Danke euch beiden :)

Werbeanzeige