Skip to main content
gamedev.net
🔒 Locked

[SDL] Another Destructor Problem

Started by Uphoreum Sep 10, 2006 at 12:06 PM 7 replies 950+ views
Original Post
Uphoreum
Uphoreum
Again, I'm having problems with destructors in my classes. I have a SDL_Surface wrapper class called Surface. By itself it works fine. Here's the code:

//SDL_Surface Wrapper Class
    class Surface
    {
    private:
        SDL_Surface* surface;

    public:
        //Default Constructor
        Surface()
        {
            surface = NULL;
        }

        //Loading Constructor
        Surface(const char* fileName)
        {
            LoadBitmap(fileName);
        }

        //SDL Surface Constructor
        Surface(SDL_Surface* newSurface)
        {
            surface = newSurface;
        }

        //Return Surface
        SDL_Surface* GetSurface()
        {
            return surface;
        }

        //Get Surface Width
        int GetWidth()
        {
            return surface->w;
        }

        //Get Surface Height
        int GetHeight()
        {
            return surface->h;
        }

        //Get Format of Surface
        SDL_PixelFormat* GetFormat()
        {
            return surface->format;
        }

        //Get Scanline Length of Surface
        Uint16 GetPitch()
        {
            return surface->pitch;
        }

        //Get Clipping rectangle of Surface
        SDL_Rect GetClip()
        {
            return surface->clip_rect;
        }

        //Get Surface Flags
        Uint32 GetFlags()
        {
            return surface->flags;
        }

        //Image Loading Method
        void LoadBitmap(const char* fileName)
        {
            //Return an optimized version of a loaded bitmap image
            surface = SDL_DisplayFormat(SDL_LoadBMP(fileName));
        }

        //Blit a surface to this surface
        void BlitTo(Surface blitSurface, Point point)
        {
            //Create Rectangle For Coordinates
            SDL_Rect destination;

            //Give Rectangle Coordinates
            destination.x = point.GetX();
            destination.y = point.GetY();

            //Blit Image to Buffer
            SDL_BlitSurface(surface, NULL, blitSurface.GetSurface(), &destination);
        }

        //Fill Surface With Color
        void Fill(int r, int g, int b)
        {
            SDL_FillRect(surface, 0, SDL_MapRGB(GetFormat(),r,g,b));
        }

        //Flip Image To Screen
        void Flip()
        {
            SDL_Flip(surface);
        }

        //Destructor
        ~Surface()
        {
            SDL_FreeSurface(surface);
        }
    };

But if I try to send it as an argument to the constructor of another class that wraps around it, like my Sprite class, then the destructor is called:

Surface mySurface("image.bmp"); //Load the surface
Sprite mySprite(mySurface); //Create a sprite with mySurface as the surface

because if I try to draw the surface after I've created the sprite that wraps around it:

mySurface.BlitTo(screen);

The program crashes. In it's desturctor, it frees the surface. If I take that line out of the destructor, every thing works fine. How can I stop the destructor from being called when I pass the surface as a parameter? I can try to give more info if it wasn't clear...
Jack Sotac
Jack Sotac
Can you show the sprite contructor? If you pass the sprite by reference or pointer that should prevent the constructor from being called.

You can also use ref counters or smart pointers to manage the destructors.

Also make sure the surface is loaded properly(check return value of SDL_LoadBMP()).

Good Luck.


[Edited by - Jack Sotac on September 10, 2006 5:05:25 PM]
0xa0000000
deathkrush
deathkrush
Quote:
Original post by Jack Sotac
Can you show the sprite contructor? If you pass the sprite by reference or pointer that should prevent the constructor from being called.


It will also prevent the destructor from being called as soon as the temp variable goes outside of the scope.
deathkrushPS3/Xbox360 Graphics Programmer, Mass Media.Completed Projects: Stuntman Ignition (PS3), Saints Row 2 (PS3), Darksiders(PS3, 360)
Uphoreum
Uphoreum
Yea, here's the constructor:

Sprite(Surface newSurface, int newX, int newY){    surface = newSurface;    x = newX;    y = newY;}


You're right, I think that would solve the problem, but I'm not sure how to implement it.
Jack Sotac
Jack Sotac
Here how to would do it.
Sprite(Surface& newSurface, int newX, int newY){    surface = newSurface;    x = newX;    y = newY;}

But it still doesn't solve the problems of:
1)mySurface going out of scope and invalidating the surface in mySprite
2)mySprite going out of scope thus invalidating the mySurface surface.

If you're not reusing the same image for different sprite you can just have the sprite load the image.
Sprite(const string& filename, int newX, int newY){    surface.LoadBitmap(filename.c_str());    x = newX;    y = newY;}...Sprite mysprite("image.bmp",0,0);

This keeps the surface and sprite in the same scope.

Good Luck.
0xa0000000
t0Xic
t0Xic
let google tell you something about: resource counting
Uphoreum
Uphoreum
Yea, I'm probably just going to seperate surface and sprite/button. There's too much unwanted pointer behavior that I can't control :-(
Taymo
Taymo
Copy your referance into the new surface. That, or use proper resource managment.
Dev Journal - Ride the Spiralhttp://spiralride.blogspot.com/
DeadXorAlive
DeadXorAlive
In addition to what's been said, the LoadBitmap function will leak: surface = SDL_DisplayFormat(SDL_LoadBMP(fileName)); SDL_LoadBMP allocates memory that is used but not freed by SDL_DisplayFormat.

If you're not familiar with it, I second looking up reference counting. SDL_Surface and SDL_FreeSurface has support for this, you can increase the reference count in the copy constructor if you want this behavior: surface->refcount++. SDL_FreeSurface decreases the refcount automatically, and if it finds no more references it frees the allocated memory. You should probably also overload the assignment operator.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.