Hello, I have been learning SDL through a set of tutorials here. The program was able to bring up the image for each key that I had added. After adding code to omptimize the images the window pops up but shows no image and if I press a key it crashes. Any help will be greatly appreciated!

#include <iostream>
#include "SDL.h"

using namespace std;

const int SCREEN_HEIGHT = 720;
const int SCREEN_WIDTH = 1080;

enum gKeyPressSurfaces
{
    KEY_PRESS_SURFACE_DEFAULT,
    KEY_PRESS_SURFACE_UP,
    KEY_PRESS_SURFACE_DOWN,
    KEY_PRESS_SURFACE_LEFT,
    KEY_PRESS_SURFACE_RIGHT,
    KEY_PRESS_SURFACE_TOTAL
};

    bool init();

    bool loadMedia();

    //The window we'll be rendering to
    SDL_Window* gWindow = NULL;

    //The surface contained by the window
    SDL_Surface* gScreenSurface = NULL;

    //The images that correspond to a keypress
    SDL_Surface* gKeyPressSurfaces[KEY_PRESS_SURFACE_TOTAL];

    //Currenty displayed image
    SDL_Surface* gCurrentSurface = NULL;

    //The image we will load and show on the screen
    SDL_Surface* loadSurface(std::string path);


    //Starts up SDL and creates window
    bool init()
    {
        //Initialization flag
        bool success = true;

        //Initialize SDL
        if( SDL_Init(SDL_INIT_VIDEO) < 0 )
        {
            cout << "SDL could not initialize! SDL_ERROR: " << SDL_GetError();
            success = false;
        }
        else
        {
            //Create window
            gWindow = SDL_CreateWindow("SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
            if(gWindow == NULL)
            {
                cout << "Window could not be created! SDL_ERROR: " << SDL_GetError();
                success = false;
            }
            else
            {
                //Get window surface
                gScreenSurface = SDL_GetWindowSurface( gWindow);
            }
            //The image we will load and show on the screen SDL_Surface* gHelloWorld = NULL;
        }
        return success;
    }

    //Loads media
    bool loadMedia()
    {
        //Loading success flag
        bool success = true;

        //Load default surface
        gKeyPressSurfaces[KEY_PRESS_SURFACE_DEFAULT] = loadSurface( "press.bmp");
        if(gKeyPressSurfaces[KEY_PRESS_SURFACE_DEFAULT] == NULL)
        {
            cout << "Failed to load the default image!\n";
            success = false;
        }

        //load up surface
        gKeyPressSurfaces[KEY_PRESS_SURFACE_UP] = loadSurface("up.bmp");
        if(gKeyPressSurfaces[KEY_PRESS_SURFACE_UP] == NULL)
        {
            cout << "Failed to load the up image!\n";
            success = false;
        }

         //load down surface
        gKeyPressSurfaces[KEY_PRESS_SURFACE_DOWN] = loadSurface("down.bmp");
        if(gKeyPressSurfaces[KEY_PRESS_SURFACE_DOWN] == NULL)
        {
            cout << "Failed to load the down image!\n";
            success = false;
        }

          //load up surface
        gKeyPressSurfaces[KEY_PRESS_SURFACE_LEFT] = loadSurface("left.bmp");
        if(gKeyPressSurfaces[KEY_PRESS_SURFACE_LEFT] == NULL)
        {
            cout << "Failed to load the left image!\n";
            success = false;
        }

          //load up surface
        gKeyPressSurfaces[KEY_PRESS_SURFACE_RIGHT] = loadSurface("right.bmp");
        if(gKeyPressSurfaces[KEY_PRESS_SURFACE_RIGHT] == NULL)
        {
            cout << "Failed to load the right image!\n";
            success = false;
        }

        return success;
    }

    //Frees media and shuts down SDL
    void close()
    {
        //Deallocate surface
        SDL_FreeSurface( gCurrentSurface);
        gCurrentSurface = NULL;

        //Destroy window
        SDL_DestroyWindow(gWindow);
        gWindow = NULL;

        //Quit SDL subsystems
        SDL_Quit();
    }

     SDL_Surface* loadSurface(std::string path)
    {
        //The final optimized image
        SDL_Surface* optimizedSurface = NULL;

        //Load image at specified path
        SDL_Surface* loadedSurface = SDL_LoadBMP(path.c_str());
        if(loadedSurface == NULL)
        {
            cout << "Unable to load image. SDL ERROR: " << path.c_str(), SDL_GetError();
            cout << endl;
        }
        else
        {
            //Convert surface to screen format
            optimizedSurface = SDL_ConvertSurface(loadedSurface, gScreenSurface->format, NULL);
            if( optimizedSurface == NULL)
            {
                cout << "Unable to optimize the image, SDL ERROR: " << path.c_str(), SDL_GetError();
                cout << endl;
            }

            //get rid of old loaded surface
            SDL_FreeSurface(loadedSurface);
        }

        return loadedSurface;
    }

int main( int argc, char* args[] )
{
    //start SDL and create window
    if( !init() )
    {
        cout << "Failed to initialize!" << endl;
    }
    else
    {

        //Load media
        if( !loadMedia())
        {
            cout << "Failed to load media!" << endl;
        }
        else
        {

            //Main loop flag
            bool quit = false;

            //Event handler
            SDL_Event e;

            //Set default current surface
            gCurrentSurface = gKeyPressSurfaces[ KEY_PRESS_SURFACE_DEFAULT];

            //Main loop
            while( !quit)
            {
                //Handle events on queue
                while( SDL_PollEvent( &e ) != 0)
                {
                    //User requests quit
                    if(e.type == SDL_QUIT)
                    {
                        quit = true;
                    }

                    //select surfaces based on keypress
                    switch(e.key.keysym.sym)
                    {
                    case SDLK_UP:
                        gCurrentSurface = gKeyPressSurfaces[KEY_PRESS_SURFACE_UP];
                        break;

                    case SDLK_DOWN:
                        gCurrentSurface = gKeyPressSurfaces[KEY_PRESS_SURFACE_DOWN];
                        break;

                    case SDLK_LEFT:
                        gCurrentSurface = gKeyPressSurfaces[KEY_PRESS_SURFACE_LEFT];
                        break;

                    case SDLK_RIGHT:
                        gCurrentSurface = gKeyPressSurfaces[KEY_PRESS_SURFACE_RIGHT];
                        break;

                    default:
                        gCurrentSurface = gKeyPressSurfaces[KEY_PRESS_SURFACE_DEFAULT];
                    }


                //Apply the image stretched
                SDL_Rect stretchRect;
                stretchRect.x = 0;
                stretchRect.y = 0;
                stretchRect.w = SCREEN_WIDTH;
                stretchRect.h = SCREEN_HEIGHT;
                SDL_BlitScaled(gCurrentSurface, NULL, gScreenSurface, &stretchRect );

                //Update surface
                SDL_UpdateWindowSurface( gWindow );
                }
            }
        }
    }

    //Free resources and close SDL
    void close();
    return 0;
}

Took me a little while to spot this, but I think you are going to kick yourself!

Have a close look at what your loadSurface function is doing:
Line 140: You load the image into an SDL_surface pointer called loadedSurface.
Line 149: if the image loaded sucessfully, you optimise the image and store it in the SDL_surface pointer called optimizedSurface
Line 157: You delete the object pointed to by loadedSurface
Line 160: You return loadedSurface (which you just deleted.... Ooops!)

So your array gets filled with invalid pointers. Therefore when you try to blit an image at line 232, you are going to get a crash!

Also, with the code as it stands: Each time the loadSurface function gets called and returns and the optimizedSurface pointer drops out of scope, the pointer to the memory containing the optimized image/surface is lost. So you also have a memory leak!

I think you want to be returning optimizedImage at line 160 instead! :)
That will stop the crash AND plug the memory leak!

Edited 2 Years Ago by JasonHippy

This article has been dead for over six months. Start a new discussion instead.