Probleme beim debuggen



  • Hallo

    Eigentlich ist der Destruktor leer. Hier die hpp und cpp Dtaei:

    h:

    #pragma once
    
    #include <iostream>
    #include "Sprite.h"
    #include <string>
    
    class CCube
    {
    public:
    	CCube(void);
    	~CCube(void);
    	void Init(int p_iBitmapPosX, int p_iBitmapPosY);
    	void Dice(void);
    	void Render(void);
    	void SetMarkedOrNonMarked(void);
    	int GetCubeState(void) const
    	{
    		return m_iCubeState;
    	}
    	int m_iCubeState;
    
    protected:
    	SDL::CSprite m_CubeSprite;
    	std::string m_strFileName;
    
    	int m_iBitmapPosX;
    	int m_iBitmapPosY;
    };
    

    und hier die cpp Datei:

    #include "Cube.h"
    
    CCube::CCube(void)
    {
    
    }
    
    CCube::~CCube(void)
    {
    
    }
    
    void CCube::Init(int p_iBitmapPosX, int p_iBitmapPosY)
    {
    	m_strFileName = "pictures/wuerfel_";
    	m_iBitmapPosX = p_iBitmapPosX;
    	m_iBitmapPosY = p_iBitmapPosY;
    
    }
    
    void CCube::Dice(void)
    {
    	m_iCubeState = rand()%6 + 1;
    }
    
    void CCube::Render(void)
    {
    	if(m_iCubeState>6)
    		m_CubeSprite.Load(m_strFileName + ConvertToString(m_iCubeState-6) + "gesetzt.bmp");
    	else
    		m_CubeSprite.Load(m_strFileName + ConvertToString(m_iCubeState) + ".bmp");
    	m_CubeSprite.SetPos(static_cast<float>(m_iBitmapPosX),static_cast<float>(m_iBitmapPosY));
    	m_CubeSprite.Render();
    }
    
    void CCube::SetMarkedOrNonMarked(void)
    {
    	if(m_iCubeState < 7)
    		m_iCubeState += 6;
    	else
    		m_iCubeState -= 6;
    }
    

    Vielleicht hilft das ja weiter.

    chrische



  • Auch wenn der Destruktor leer aussieht, packt der Compiler da noch einiges rein - nämlich die Dtor-Aufrufe der Elementvariablen (string und int dürften harmlos sein, aber was ist mit CSprite?)

    PS: ist das richtig so, daß 'm_iCubeState' öffentlich ist?



  • Hallo

    Ja es ist richtig, dass m_iCubeState public ist. Das will ich später noch ändern, aber zum Testen geht es so einfach schneller.

    Hier jetzt noch einmal h und cpp Datei von Sprite:

    h Datei:

    #pragma once
    
    #include "Framework.h"
    
    namespace SDL
    {
    	class CSprite
    	{
    	public:
    		CSprite(void);
    		~CSprite(void);
    		void Load(const std::string p_strFileName);
    		void Load(std::string p_strFileName, int p_iNumFrames, int p_iFrameWidth, int p_iFrameHeight);
    		void SetColorKey(Uint8 p_iR, Uint8 p_iG, Uint8 p_iB);
    		void SetPos(float p_fXPos, float p_fYPos);
    		void Render(void);
    		void Render(float p_fFrameNumber);
    		SDL_Rect GetRect(void) {return m_Rect;}
    
    	private:
    		SDL_Surface* m_pScreen;		//Zeiger auf den Screen des Frameworks
    		SDL_Surface* m_pImage;		//das eigentliche des Sprites
    		SDL_Rect	 m_Rect;		//Rect des Sprites
    		SDL_Rect	 m_FrameRect;	//Ausschnitt für Animatiomsphase
    		int			 m_iNumFrames;	//Anzahl der Animationsphasen
    		int			 m_iFrameWidth;	//Breite der Animationsphase
    		int			 m_iFrameHeight;//Höhe einer Animatiosphase
    		int			 m_iNumFramesX;	//Wie viele Animationsphasen in X-Richtung 
    	};
    }
    

    und die cpp Datei:

    #include "StdAfx.h"
    #include ".\sprite.h"
    
    using namespace SDL;
    
    CSprite::CSprite(void)
    : m_pScreen(Framework->GetScreen())
    , m_pImage(NULL)
    {
    }
    
    CSprite::~CSprite(void)
    {
    	SDL_FreeSurface(m_pImage);
    }
    
    void CSprite::Load(const std::string p_strFileName)
    {
    	//Bitmap laden
    	m_pImage = SDL_LoadBMP(p_strFileName.c_str());
    
    	//Prüfen ob alles glatt ging
    	if(m_pImage == NULL)
    	{
    		Logfile->WriteTopic("Laden des Bitmaps",3);
    		Logfile->TextOut("Laden des Bitmaps ist fehlgeschlagen<br>");
    		std::string strErrorCode = SDL_GetError();
    		Logfile->TextOut("Fehler: " + strErrorCode + "<br>");
    
    		Framework->Quit();
    
    		exit(1);
    	}
    
    	//Rect initialisieren
    	m_Rect.x = 0;
    	m_Rect.y = 0;
    	m_Rect.w = static_cast<Uint16>(m_pImage->w);
    	m_Rect.h = static_cast<Uint16>(m_pImage->h);
    }
    
    void CSprite::Load(std::string p_strFileName, int p_iNumFrames, int p_iFrameWidth, int p_iFrameHeight)
    {
    	Load(p_strFileName);
    
    	m_iNumFrames	= p_iNumFrames;
    	m_iFrameWidth	= p_iFrameWidth;
    	m_iFrameHeight	= p_iFrameHeight;
    	m_FrameRect.w	= static_cast<Uint16>(p_iFrameWidth);
    	m_FrameRect.h	= static_cast<Uint16>(p_iFrameHeight);
    	m_iNumFramesX	= m_pImage->w / m_iFrameWidth;
    }
    
    void CSprite::SetColorKey(Uint8 p_iR, Uint8 p_iG, Uint8 p_iB)
    {
    	//Colorkey einstellen
    	SDL_SetColorKey(m_pImage, SDL_SRCCOLORKEY, SDL_MapRGB(m_pImage->format,p_iR, p_iG, p_iB));
    }
    
    void CSprite::SetPos(float p_fXPos, float p_fYPos)
    {
    	m_Rect.x = static_cast<Sint16>(p_fXPos);
    	m_Rect.y = static_cast<Sint16>(p_fYPos);
    }
    
    void CSprite::Render(void)
    {
    	SDL_BlitSurface(m_pImage, NULL, m_pScreen, &m_Rect);
    }
    
    void CSprite::Render(float p_fFrameNumber)
    {
    	//Ausschnitt der aktuellen Animationsphase berechnen
    
    	//Spalte berechnen
    	int iColumn = static_cast<Sint16>(p_fFrameNumber)%m_iNumFramesX;
    
    	//Zeile berechnen
    	int iRow = static_cast<Sint16>(p_fFrameNumber/m_iNumFramesX);
    
    	//Rect berechnen
    	m_FrameRect.x = static_cast<Sint16>(iColumn * m_iFrameWidth);
    	m_FrameRect.y = static_cast<Sint16>(iRow * m_iFrameHeight);
    
    	//Ausschnitt rendern
    	SDL_BlitSurface(m_pImage, &m_FrameRect, m_pScreen, &m_Rect);
    }
    

    Mal schauen, ob Ihr was findet.

    Vielen Dank für Eure Hilfe.

    chrische



  • Du hast keinen Kopierkonstruktor/Zuweisungsoperator für die CSprite und die Standardversion verträgt sich nicht sonderlich mit dynamischer Speicherverwaltung (wenn ein CSprite kopiert wird, zeigen m_pScreen und m_sImage auf den Bereich, den das Original angelegt hat - und anschließend versuchen beide Objekte, diesen Bereich freizugeben).



  • m_pScreen sollte hier keine Probleme verursachen, da es nicht im Destruktor freigegeben wird. Wegen m_pImage ist aber natürlich ein CopyKonstruktor erforderlich.



  • Hallo

    Sorry, aber das verstehe ich nicht. Wo wird den kopiert und außerdem habe ich in einem anderen Programm genau diese Version von CSprite benutzt ohne das es Probleme gab.

    chrische



  • Hallo

    Ich würde gerne noch einmal meine Frage vom letzten Post wiederholen. Ich habe nun noch einen Kopüierkonstruktor hinzugefügt und ich habe immernoch das selbe, oben beschriebene, Problem.

    chrische



  • Elemente für einen std::ector müssen Copyconstructable sein.
    du must im CCtor auch den inhalt des Pointers auf dein Image kopieren.
    http://www.cs.wisc.edu/~hasti/cs368/CppTutorial/NOTES/CLASSES-PTRS.html



  • Hallo

    Ich bin mir nicht sicher, ob mein Copyconstructor richtig ist, weil ich sowas noch nie geschrieben habe, also zeige ich ihn Euch mit der Bitte mir den Sand aus den Augen zu waschen.

    CSprite::CSprite(const CSprite& rhs)
    {
    	m_pImage = new SDL_Surface;
    	m_pImage = rhs.m_pImage;
    	m_pScreen = rhs.m_pScreen;
    	m_Rect = rhs.m_Rect;
    	m_FrameRect = rhs.m_FrameRect;
    	m_iFrameHeight = rhs.m_iFrameHeight;
    	m_iFrameWidth = rhs.m_iFrameWidth;
    	m_iNumFrames = rhs.m_iNumFrames;
    	m_iNumFramesX = rhs.m_iNumFramesX;
    }
    

    Rest der Klasse siehe oben.

    chrische



  • Nein der ist nicht gut

    CSprite::CSprite(const CSprite& rhs)
    {
    	m_pImage = new SDL_Surface;
    	m_pImage = rhs.m_pImage;
            .....
    }
    

    du erzeugst erst mal eine neue SDL_Surface und mit der nächsten Istruktion überschreibst du sie schon wieder --> Speicherleck
    Kurt



  • Hallo

    Dann kapiere ich einfach nicht, wie das gehen soll. Kann mir mal jemand einen Anstoss geben.

    chrische



  • Hallo

    Es weiß doch bestimmt einer von Euch, wie der korrekte Copyconstructor aussehen muss.

    chrische



  • Nö.



  • chrische5 schrieb:

    Es weiß doch bestimmt einer von Euch, wie der korrekte Copyconstructor aussehen muss.

    Kommt ganz drauf an was SDL_Surface ist
    Wahrscheinlich so wenn SDL_Surface einen Copyconstructor hat.

    CSprite::CSprite(const CSprite& rhs)
    {
        m_pImage = new SDL_Surface(*rhs.m_pImage);
            .....
    }
    

    das könnte eventuell auch funktionieren wenn z.B. SDL_Surface nur ein typedef für ein char array ist

    CSprite::CSprite(const CSprite& rhs)
    {
        m_pImage = new SDL_Surface;
        memcpy(m_pImage, rhs.m_pImage , sizeof(SDL_Surface));
            .....
    }
    

    Langer Rede kurzer Sinn: keiner kann dir sagen wie dein copyconstructor aussehen muss wenn du uns nicht sagst woraus genau dein CSprite besteht.
    Kurt



  • Hallo

    Erstmal dank für deine Antwort. Dieses Thema ist halt noch neu für mich. Den kompletten Code der Klasse steht doch schon im Forum nur ein paar Post weiter oben (früher). Brauchst du noch mehr Information?

    chrische



  • chrische5 schrieb:

    Erstmal dank für deine Antwort. Dieses Thema ist halt noch neu für mich. Den kompletten Code der Klasse steht doch schon im Forum nur ein paar Post weiter oben (früher). Brauchst du noch mehr Information?

    In deinem Fall geht's nicht um deinen Code. Es geht darum wie das ganze Framework funktioniert mit dem du da arbeitest. Wer das nicht kennt kann dir auch keine allgemeine Antwort geben wie man daraus eigene Klassen ableitet.
    Kurt



  • Hallo

    Danke für deine Hilfe. Ich werde jetzt mal versuchen deine Anregungen umzusetzten.

    chrische


Anmelden zum Antworten