Absturz beim einfügen eines Listenelements



  • Hallo!

    Ich versuche mich gerade an meinem ersten Spiel mit DirectX. Es soll ein Tetris Clone werden. Bisher hatte auch alles soweit nach Plan geklappt. Jetzt bin ich aber an dem Punkt angekommen, bei dem die Steine im Feld liegen bleiben sollen. Das versuche ich mit einer Liste zu realisieren. D.h., wenn eine komletter Tetrisstein auf dem Boden (oder später anderen Steinen) aufkommt, werden die einzelnen Steine in eine Liste gespeichert und der TetrisStein wird zerstört, damit ein Neuer runterregnen kann. Soweit so gut ... ich habe jetzt also eine Liste für die Steine geschreiben:

    #pragma once
    #include "EinzelStein.h"
    #include "Feld.h"
    #include <ddraw.h>
    
    class SteinListe {
    private:
    	class Knoten {
    	private:
    		EinzelStein* Stein;
    		Knoten* Next;
    
    	public:
    		Knoten() {
    			Next  = NULL;
    		}
    
    		~Knoten();
    
    		void SetNext(Knoten* kn) {
    			Next = kn;
    		}
    
    		Knoten* GetNext() {
    			return Next;
    		}
    
    		bool HasNext() {
    			if (Next != NULL)
    				return TRUE;
    			else
    				return FALSE;
    		}
    
    		void SetStein(EinzelStein* _Stein) {
    			Stein = _Stein;
    		}
    
    		EinzelStein* GetStein() {
    			return Stein;
    		}
    	};
    
    	Feld* Spielfeld;
    
    	Knoten* Head;
    	Knoten* End;
    
    public:
    	SteinListe(Feld* _Spielfeld);
    	~SteinListe(void);
    
    	void Add(EinzelStein* _Stein);
    	void Delete(int x, int y);
    
    	void Draw(LPDIRECTDRAWSURFACE7 lpDDSurface);
    };
    

    Sobald ich jetzt Head oder End einen Knoten zuweise (wenn der erste Tetrisstein auf dem Boden aufkommt), bleibt das Programm hängen. Ich weiss durch den Debugger auch genau, an welcher Stelle. In der Add-Funktion:

    void SteinListe::Add(EinzelStein* _Stein) {
    	Knoten* kn;
    	kn = new Knoten();
    	kn->SetStein(_Stein);
    
    	if (Head == NULL) {
    		Head = End = kn;
    	}
    	else {
    		End->SetNext(kn);
    		End = End->GetNext();
    	}
    }
    

    Sobald ich den IF-Block weg mach läuft alles Prima, außer dass die Steine auf dem Boden liegen bleiben. Es stürzt übrigens auch ab, wenn ich statt dem IF-Block nur

    Head = kn;
    

    schreibe.

    Ich habe jetzt schon öfters mit Listen gearbeitet und auch mal die lauffähigen Versionen mit dieser hier verglichen. Ich kann aber keinen Unterschied feststellen. Ich verstehe einfach nicht, wieso das nicht läuft.



  • Kannst du mal den Konstruktor der Liste zeigen? Ich hoffe doch, du hast dort Head mit einem brauchbaren Wert initialisiert.



  • SteinListe::SteinListe(Feld* _Spielfeld) {
    	Head = End = NULL;
    	Spielfeld = _Spielfeld;
    }
    


  • Ich habe mal Screenshots von den Debuggermeldungen gemacht ...

    http://www.bilder-hochladen.net/files/4s4s-1-jpg.html
    http://www.bilder-hochladen.net/files/4s4s-2-jpg.html

    ... vielleicht hilft das ja weiter.



  • Sehe ich das richtig, this ist 0x0000? Wie hast du denn deine Steinliste angelegt?



  • Hier ist ein kurzer Auschnitt meiner MainFunktion, in der die Liste angelegt wird:

    Feld* Spielfeld;
    VollStein* MainStein;
    SteinListe* Liste;
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
    	hWnd = CreateMainWindow(hInstance);
    
    	if (hWnd == 0){
    		MessageBox(0, "Fenster konnte nicht erzeugt werde", "Fehler", MB_OK);
    		return 0;
    	}
    
    	if (!ddc.Init(hWnd)) {
    		MessageBox(hWnd, "Fehler beim initialisieren von DirectDraw", "Fehler", MB_OK);
    		return 0;
    	}
    
    	Spielfeld = new Feld(10, 10, 8, 13, 35);
    	MainStein = new VollStein(3, CalcColor(rand()%256, rand()%256, rand()%256), Spielfeld, Liste);
    	Liste = new SteinListe(Spielfeld);
    
    	ZeroGame();
    


  • Und wer ruft das Add() auf? Hoffentlich nicht der Konstruktor von MainStein (wenn der durchlaufen wird, existiert deine Liste noch gar nicht).

    PS: Du wirfst sehr viel mit Zeigern um dich - ich hoffe, dir ist klar, daß du auch alles wieder freigeben mußt, was du mit new angefordert hast.



  • Das Add() wird zwar in MainStein aufgerufen, aber nicht im Konstruktor. Sondern, wenn der Stein auf den "Boden" trifft. Zu dem Zeitpunkt ist die Liste schon längst da.



  • Hier ist der Code vom MainStein, der bei case: DOWN die Funktion Release() aufruft, in welcher dann die Stein mit Add() hinzugefügt werden:

    void VollStein::Move(int d) {
    	bool admission = TRUE;
    
    	switch (d) {
    		case LEFT:
    			if (KollisionsTest(PosX-1, PosY) == 1) {
    				PosX--;
    				for (int i = 0; i < 4; i++) Stein[i]->SetPos(PosX + SteinPos[i].x, PosY + SteinPos[i].y);
    			}
    			break;
    
    		case RIGHT:
    			if (KollisionsTest(PosX+1, PosY) == 1) {
    				PosX++;
    				for (int i = 0; i < 4; i++) Stein[i]->SetPos(PosX + SteinPos[i].x, PosY + SteinPos[i].y);
    			}
    			break;
    
    		case DOWN:
    			if (KollisionsTest(PosX, PosY+1) == 1) {
    				PosY++;
    				for (int i = 0; i < 4; i++) Stein[i]->SetPos(PosX + SteinPos[i].x, PosY + SteinPos[i].y);
    			}
    			else
    				Release();
    
    			break;
    	}
    }
    

    Hier werden die Steine dann zur Liste hinzugefügt.

    void VollStein::Release() {
    	for (int i = 0; i < 4; i++) Liste->Add(Stein[i]);
    
    	Released = TRUE;
    }
    


  • Ich hab den Fehler gefunden!

    Grendel schrieb:

    ich habe jetzt also eine Liste für die Steine geschreiben:

    Diesen Code solltest du in

    #include <list>
    
    typedef std::list<EinzelStein*> SteinListe;
    

    umändern.

    Und falls du doch ganz unbedingt noch andere, nicht-listige Sachen in deiner Liste brauchst:

    #include <list>
    
    class SteinListe
    {
    public:
      // dein Kram hier
    
    private:
      std::list<EinzelStein*> steine_;
    };
    


  • Ok, vielen Dank für die Hilfe! Allerdings habe ich keine Ahnung, worum es in dem Code geht. In dem Buch, was ich durchgearbeitet habe, steht nichts brauchbares drin und ehrlich gesagt, kapier ich immernoch nicht so ganz, wie der Fehler verursacht wird. Gibt es dazu vielleicht Tutorials (oder besser noch Bücher), die Du mir empfehlen kannst?


Anmelden zum Antworten