Weird SDL Error

Started by
4 comments, last by Dante12129 11 years, 1 month ago

I am having weird behavior in my SDL application. I am making a game engine and I have a project to test it, and am dynamically linking the test project to the engine. The problem is that the program seems to run fine sometimes and bad other times. If it doesn't work, it'll do everything fine until it closes the window, where it'll close the window and the pause for a few seconds before saying that it terminated with status -1073741819. Here's my code:

Engine, Screen.hpp


#ifndef SCREEN_HPP_INCLUDED
#define SCREEN_HPP_INCLUDED

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

namespace myeng
{
    class Screen final //This class doesn't need to be derived from
    {
        public:

            //Constructor and destructor
            Screen(int height, int width, std::string caption);
            ~Screen();

            //Functions to get the width, height, and depth of the screen
            int getScreen_Width();
            int getScreen_Height();
            int getScreen_Depth();

            //Function to get screen_ptr
            SDL_Surface* getScreen_Ptr();

            //Function to flip the screen
            int Screen_Flip();

            //Function to put something on the screen
            int Screen_Put(int x, int y, SDL_Surface* source);

            //Functions for backgrounds
            int Screen_RepBack(int height, int width, SDL_Surface* source);

        private:
            //Constants
            const int SCREEN_WIDTH = 0;
            const int SCREEN_HEIGHT = 0;
            const int SCREEN_DEPTH = 0;

            //Other variables
            std::string screen_name;

            //Surfaces
            SDL_Surface* screen_ptr = nullptr; //Creates the main surface for the screen
    };
}

#endif // SCREEN_HPP_INCLUDED

Screen.cpp


#include <iostream>
#include "Screen.hpp"

//Cosntructor and destructor
myeng::Screen::Screen(int height, int width, std::string caption)
{
    const_cast<int&> (SCREEN_WIDTH) = width;
    const_cast<int&> (SCREEN_HEIGHT) = height;
    const_cast<int&> (SCREEN_DEPTH) = 32;
    screen_ptr = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_DEPTH, SDL_SWSURFACE);
    screen_name = caption;
}
myeng::Screen::~Screen()
{
    SDL_FreeSurface(screen_ptr);
}

//Functions to get width, height, and depth of the screen
int myeng::Screen::getScreen_Width()
{
    return SCREEN_WIDTH;
}
int myeng::Screen::getScreen_Height()
{
    return SCREEN_HEIGHT;
}
int myeng::Screen::getScreen_Depth()
{
    return SCREEN_DEPTH;
}

//Function to get screen_ptr
SDL_Surface* myeng::Screen::getScreen_Ptr()
{
    return screen_ptr;
}

//Function to flip the screen
int myeng::Screen::Screen_Flip()
{
    if(SDL_Flip(screen_ptr) != 0)
    {
        std::cerr << "Failed to flip screen. Error" << SDL_GetError() << "\n";
        return 1;
    }
    else
    {
        return 0;
    }
}

//Function to put something on the Screen
int myeng::Screen::Screen_Put(int x, int y, SDL_Surface* source)
{
    //Create a rectangle to store the offsets of the source
    SDL_Rect offset;

    //Set the offsets
    offset.x = x;
    offset.y = y;

    //Apply the source to the screen
    if(SDL_BlitSurface(source, nullptr, screen_ptr, &offset) != 0)
    {
        std::cerr << "Failed to blit the surface. Error " << SDL_GetError();
        return 1;
    }
    else
    {
        return 0;
    }
}

//Functions for backgrounds
int myeng::Screen::Screen_RepBack(int height, int width, SDL_Surface* source)
{
    int columns = SCREEN_HEIGHT / height;
    int rows = SCREEN_WIDTH / width;

    if((SCREEN_HEIGHT % height != 0) || (SCREEN_WIDTH % width != 0))
    {
        std::cerr << "Background cannot be repeated over the screen \n";
        return 1;
    }
    else
    {
        for(int i = 0; i < columns; i++)
        {
            for(int j = 0; j < rows; j++)
            {
                Screen_Put(j*width, i*height, source);
            }
        }
    }
    return 0;
}

Test Project, main.cpp


#include <iostream>
#include "SDL_Image.h"
#include "Screen.hpp"

SDL_Surface* load_image(std::string filename, bool maketransparent = false)
{
    //The image that's loaded
    SDL_Surface* loadedImage = NULL;

    //The optimized image that will be used
    SDL_Surface* optimizedImage = NULL;

    //Load the image
    loadedImage = IMG_Load( filename.c_str() );

    //If the image loaded
    if( loadedImage != NULL )
    {
        //Log the image loading
        std::cout << "Successfully loaded: " << filename << "\n";

        //Create an optimized image
        optimizedImage = SDL_DisplayFormat( loadedImage );

        //Free the old image
        SDL_FreeSurface( loadedImage );

        //If the image was optimized just fine and the user specifies transparency
        if( optimizedImage != NULL && maketransparent == true )
        {
            //Log the optimization
            std::cout << "Generated optimized image for: " << filename << "\n";

            //Map the color key
            Uint32 colorkey = SDL_MapRGB( optimizedImage->format, 0xED, 0x0B, 0xB5 );

            //Set all pixels of color R 0xED, G 0x0B, B 0xB5 to be transparent
            SDL_SetColorKey( optimizedImage, SDL_SRCCOLORKEY, colorkey );

            //Log the image transparency
            std::cout << "Color-keyed: " << filename << "\n";
        }
        else
        {
            //Log the generated image
            std::cout << "Generated optimized image for: " << filename << ", no color key\n";
        }
    }
    else
    {
        std::cerr << "Failed to load: " << filename;
    }

    //Return the optimized image
    return optimizedImage;
}

int main ( int argc, char* argv[] )
{
    SDL_Surface* background = nullptr;

    if(SDL_Init(SDL_INIT_EVERYTHING) != 0)
    {
        std::cerr << "Failed to inialize SDL. Error:  " << SDL_GetError() << "\n";
        return 1;
    }

    myeng::Screen main_screen(600, 600, "Test");
    SDL_WM_SetCaption("Test", "Test");
    background = load_image("Background.png");

    main_screen.Screen_RepBack(200, 200, background);

    if(main_screen.Screen_Flip() != 0)
    {
        std::cerr << "Error flipping screen at line " << __LINE__ << "\n";
    }

    std::cout << main_screen.getScreen_Width() << "\n";
    std::cout << main_screen.getScreen_Height() << "\n";
    std::cout << main_screen.getScreen_Depth() << "\n";

    SDL_Delay(1000);
    SDL_FreeSurface(background);
    SDL_Quit();
    return 0;
}

Advertisement

The error message -1073741819, if you convert it to unsigned, is 3221225477, which when converted to hexadecimal is C0000005.

This Microsoft Windows error says:

0xC0000005 - STATUS_ACCESS_VIOLATION
The instruction at 0x%08lx referenced memory at 0x%08lx. The memory could not be %s.
For example, The instruction at [instruction address] referenced memory at [memory it's operating on]. The memory could not be [read? written to?].
I don't recall that specific error, so my interpretation of that error might be flawed, but it sounds like your program is trying to access memory outside the portion that the OS gave it to work with. This is a good safety feature of OSes. Better to give an error, then for your program to accidentally override another program's (like the OS) memory while it is running.
You probably have a pointer that's not initialized, and the value of the pointer it happens to be pointing outside your memory range.
Sometimes it happens to be outside your memory range, and gives an error, other times it happens to be inside your memory range, writes in the wrong place, and crashes. Maybe. mellow.png
I don't instantly spot any mistakes, but your manipulation of const variables looks suspicious.
This code:
const_cast<int&> (SCREEN_WIDTH) = width;
const_cast<int&> (SCREEN_HEIGHT) = height;
const_cast<int&> (SCREEN_DEPTH) = 32;

That's a bad code smell. If it's const, why are you making it non-const? You are breaking the constness of that.

You could do the exact same thing, using the constructor initialization list:

myeng::Screen::Screen(int height, int width, std::string caption) : SCREEN_WIDTH(width), SCREEN_HEIGHT(height), SCREEN_DEPTH(32)
{
    //other stuff...
}

That might not be your problem... but I wonder if the const variable, being const, is written directly into the DLL's address space, and your breaking of the const is trying to write to the DLL's address space instead of your program's address space? I don't have a clue, I'm not experienced in the inner working of executables and DLLs, but that'd be my starting point of researching the problem.

I looked through your code briefly but didn't find anything. You might want to google SIGSEGV and see how too solve and prevent these kinds of issues. SIGSEGVs is basically access violation.

I also recommend you to use some kind of debugger, (GDB for example). Finally taking a look at your call stack can also provide you with some hints.

If you don't understand the stuff written here, please sharpen your C++ skills.

I removed the const and const_casts but it will still randomly give me the error. I ran the debugger from Code::Blocks and it says that I am getting the segmentation fault from SDL_UnlockSurface. Here's my log:

Setting breakpoints
Debugger name and version: GNU gdb (GDB) 7.5
Child process PID: 2728
Program received signal SIGSEGV, Segmentation fault.
In SDL_UnlockSurface () (C:\Users\Main\Documents\Programs\Game_Engine_Test\bin\Debug\SDL.dll)
The call stack lists SDL_UnlockSurface(), SDL_FreeSurface(), ZN5myeng6ScreenD@Ev(), msvcrt!_lock(), and some hex numbers as the calls.

The callstack is saying that this line is crashing:


myeng::Screen::~Screen()
{
    SDL_FreeSurface(screen_ptr);
}

(I'm guessing that ZN5myeng6ScreenD@Ev() is the mangled name for the myeng::Screen's destructor - but I think it's the correct guess)

I had forgotten that the SDL_Surface returned by SDL_SetVideoMode() is not supposed to be freed manually, and is instead freed automaticly by SDL_Quit(), so it's accidentally freeing the same surface twice and crashing. Just remove 'SDL_FreeSurface(screen_ptr);', and it should work fine.

That worked, thanks.

This topic is closed to new replies.

Advertisement