Thread: SDL program returns 3, debugger gives Segmentation fault

  1. #1
    Registered User Kain's Avatar
    Join Date
    Nov 2012
    Posts
    17

    SDL program returns 3, debugger gives Segmentation fault

    Hello, I'm new to programming, and I'm trying to learn SDL using (mostly) LazyFoo's tutorials.

    I'm using Code::Blocks in Windows XP, and when trying to run my program, it returns 3. The code is below, I think the problem is in the loadf() function, but I can't find it.

    I tried to use the debugger, which gives me the message below:

    Code:
    Program received signal SIGSEGV, Segmentation fault. In ?? () ()

    If I'm not mistaken, this message means that the program is referencing a rogue pointer, or generally a piece of memory it is not supposed to. But I check my code again and again, and I can't find where the problem is.

    The files work perfectly in my previous simpler programs, and the load() and loadf() code is nearly identical.

    I'm really not very experienced, since I only started learning programming about two months ago, and some help with this would really be appreciated.

    Please excuse the length of the code. I post all of it here because I don't know what function the problem is in.

    Thank you in advance.


    Code:
    #include "SDL/SDL.h"
    #include "SDL/SDL_image.h"
    #include "SDL/SDL_ttf.h"
    #include "SDL/SDL_mixer.h"
    #include <string>
    
    const int SW = 640;
    const int SH = 480;
    const int BPP = 32;
    
    SDL_Surface * screen = NULL;
    SDL_Surface * background = NULL;
    SDL_Surface * faces = NULL;
    SDL_Surface * text = NULL;
    
    Mix_Chunk * up = NULL;
    Mix_Chunk * down = NULL;
    Mix_Chunk * left = NULL;
    Mix_Chunk * right = NULL;
    
    SDL_Rect clip[5];
    
    SDL_Event event;
    
    TTF_Font * font = NULL;
    SDL_Color tcolor = { 255 , 255 , 255 };
    
    bool init()
    {
        if( SDL_Init( SDL_INIT_EVERYTHING ) == -1 )
        {
            return false;
        }
    
        screen = SDL_SetVideoMode( SW , SH , BPP , SDL_SWSURFACE );
    
        if( screen == NULL || TTF_Init() == -1 )
        {
            return false;
        }
    
        if( Mix_OpenAudio( 22050 , MIX_DEFAULT_FORMAT , 2 , 4096 ) == -1 )
        {
            return false;
        }
    
        SDL_WM_SetCaption( "Directions w/ sound!" , NULL );
    
        return true;
    }
    
    void clean()
    {
        SDL_FreeSurface( background );
        SDL_FreeSurface( faces );
        SDL_FreeSurface( text );
    
        Mix_FreeChunk( up );
        Mix_FreeChunk( down );
        Mix_FreeChunk( left );
        Mix_FreeChunk( right );
        Mix_CloseAudio();
    
        TTF_CloseFont( font );
        TTF_Quit();
    
        SDL_Quit();
    }
    
    SDL_Surface * load( std::string file )
    {
        SDL_Surface * loaded = NULL;
        SDL_Surface * optimized = NULL;
    
        loaded = IMG_Load( file.c_str() );
    
        if( loaded != NULL )
        {
            optimized = SDL_DisplayFormatAlpha( loaded );
            SDL_FreeSurface( loaded );
        }
    
        return optimized;
    }
    
    bool loadf()
    {
        background = load( "bg.png" );
        faces = load( "d.png" );
        font = TTF_OpenFont( "Qarmic_sans_Abridged.ttf" , 24 );
    
        if( background == NULL )
        {
            return false;
        }
    
        if( faces == NULL )
        {
            return false;
        }
    
        if( font == NULL )
        {
            return false;
        }
    
        up = Mix_LoadWAV( "up.wav" );
        down = Mix_LoadWAV( "down.wav" );
        left = Mix_LoadWAV( "left.wav" );
        right = Mix_LoadWAV( "right.wav" );
    
        if( up == NULL || down == NULL || left == NULL || right == NULL )
        {
            return false;
        }
    
        return true;
    }
    
    void apply( int x , int y , SDL_Surface * get = NULL , SDL_Surface * give = NULL , SDL_Rect * clips = NULL )
    {
        SDL_Rect off;
    
        off.x = x;
        off.y = y;
    
        SDL_BlitSurface( get , clips , give , &off );
    }
    
    void clipping()
    {
        clip[0].x = 0;
        clip[0].y = 0;
        clip[0].w = 100;
        clip[0].h = 100;
    
        clip[1].x = 100;
        clip[1].y = 0;
        clip[1].w = 100;
        clip[1].h = 100;
    
        clip[2].x = 0;
        clip[2].y = 100;
        clip[2].w = 100;
        clip[2].h = 100;
    
        clip[3].x = 100;
        clip[3].y = 100;
        clip[3].w = 100;
        clip[3].h = 100;
    
        clip[4].x = 0;
        clip[4].y = 200;
        clip[4].w = 100;
        clip[4].h = 100;
    }
    
    int run( int num , std::string direct , int fw , int fh , int tw , int th )
    {
        text = TTF_RenderText_Solid( font , direct.c_str() , tcolor );
    
        if( text != NULL )
        {
            apply( 0 , 0 , background , screen );
            apply( fw , fh , faces , screen , &clip[num] );
            apply( tw , th , text , screen );
        }
    
        if( SDL_Flip( screen ) == -1 )
        {
            return 1;
        }
    }
    
    int main( int argc , char * args[] )
    {
        bool quit = false;
    
        if( init() == false )
        {
            return 2;
        }
    
        if( loadf() == false )
        {
            return 3;
        }
    
        if( clip != NULL )
        {
            clipping();
        }
    
        run( 0 , "Center!" , 290 , 180 , ( SW - text->w ) / 2 , 290 );
    
        while( quit == false )
        {
            while( SDL_PollEvent( &event ) )
            {
                if( event.type == SDL_QUIT )
                {
                    quit = true;
                }
            }
    
            Uint8 * keys = SDL_GetKeyState( NULL );
    
            if( keys[SDLK_UP] )
            {
                run( 1 , "Up!" , 290 , 10 , ( SW - text->w ) / 2 , 120 );
    
                if( Mix_PlayChannel( -1 , up , 0 ) == -1 )
                {
                    return 4;
                }
            }
    
            if( keys[SDLK_DOWN] )
            {
                run( 2 , "Down!" , 290 , 500 , ( SW - text->w ) / 2 , 600 );
    
                if( Mix_PlayChannel( -1 , down , 0 ) == -1 )
                {
                    return 4;
                }
            }
    
            if( keys[SDLK_LEFT] )
            {
                run( 3 , "Left!" , 10 , 190 , 10 , 290 );
    
                if( Mix_PlayChannel( -1 , left , 0 ) == -1 )
                {
                    return 4;
                }
            }
    
            if( keys[SDLK_RIGHT] )
            {
                run( 4 , "Right!" , 370 , 190 , 370 , 290 );
    
                if( Mix_PlayChannel( -1 , right , 0 ) )
                {
                    return 4;
                }
            }
    
            if( keys[SDLK_SPACE] )
            {
                run( 0 , "Center!" , 290 , 180 , ( SW - text->w ) / 2 , 290 );
            }
        }
    
        clean();
    
        return 0;
    }

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Code:
    Program received signal SIGSEGV, Segmentation fault.
    0x000000000040161d in main (argc=1, args=0x7fffffffe278) at bar.cpp:194
    194	    run( 0 , "Center!" , 290 , 180 , ( SW - text->w ) / 2 , 290 );
    (gdb) print SW
    $1 = 640
    (gdb) print text
    $2 = (SDL_Surface *) 0x0
    (gdb)
    You don't set text until the function is called.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User Kain's Avatar
    Join Date
    Nov 2012
    Posts
    17
    Thanks a ton!

    I re-wrote the code correctly this time, and now it (sort of) works.
    It has some problem playing the sounds, some times at the first keystroke, other times at the second, but I'll try to figure this one out by myself.

    Again, thank you very much for the help!

    Code:
    #include "SDL/SDL.h"
    #include "SDL/SDL_image.h"
    #include "SDL/SDL_ttf.h"
    #include "SDL/SDL_mixer.h"
    #include <string>
    
    const int SW = 640;
    const int SH = 480;
    const int BPP = 32;
    
    SDL_Surface * screen = NULL;
    SDL_Surface * background = NULL;
    SDL_Surface * faces = NULL;
    SDL_Surface * text = NULL;
    
    Mix_Chunk * up = NULL;
    Mix_Chunk * down = NULL;
    Mix_Chunk * left = NULL;
    Mix_Chunk * right = NULL;
    
    SDL_Rect clip[5];
    
    SDL_Event event;
    
    TTF_Font * font = NULL;
    SDL_Color tcolor = { 255 , 255 , 255 };
    
    bool init()
    {
        if( SDL_Init( SDL_INIT_EVERYTHING ) == -1 )
        {
            return false;
        }
    
        screen = SDL_SetVideoMode( SW , SH , BPP , SDL_SWSURFACE );
    
        if( screen == NULL || TTF_Init() == -1 )
        {
            return false;
        }
    
        if( Mix_OpenAudio( 22050 , MIX_DEFAULT_FORMAT , 2 , 4096 ) == -1 )
        {
            return false;
        }
    
        SDL_WM_SetCaption( "Directions w/ sound!" , NULL );
    
        return true;
    }
    
    void clean()
    {
        SDL_FreeSurface( background );
        SDL_FreeSurface( faces );
        SDL_FreeSurface( text );
    
        TTF_CloseFont( font );
        TTF_Quit();
    
        Mix_FreeChunk( up );
        Mix_FreeChunk( down );
        Mix_FreeChunk( left );
        Mix_FreeChunk( right );
        Mix_CloseAudio();
    
        SDL_Quit();
    }
    
    SDL_Surface * load( std::string file )
    {
        SDL_Surface * loaded = NULL;
        SDL_Surface * optimized = NULL;
    
        loaded = IMG_Load( file.c_str() );
    
        if( loaded != NULL )
        {
            optimized = SDL_DisplayFormatAlpha( loaded );
            SDL_FreeSurface( loaded );
        }
    
        return optimized;
    }
    
    bool loadf()
    {
        background = load( "bg.png" );
        faces = load( "d.png" );
        font = TTF_OpenFont( "Qarmic_sans_Abridged.ttf" , 24 );
    
        if( background == NULL )
        {
            return false;
        }
    
        if( faces == NULL )
        {
            return false;
        }
    
        if( font == NULL )
        {
            return false;
        }
    
        up = Mix_LoadWAV( "up.wav" );
        down = Mix_LoadWAV( "down.wav" );
        left = Mix_LoadWAV( "left.wav" );
        right = Mix_LoadWAV( "right.wav" );
    
        if( up == NULL || down == NULL || left == NULL || right == NULL )
        {
            return false;
        }
    
        return true;
    }
    
    void apply( int x , int y , SDL_Surface * get = NULL , SDL_Surface * give = NULL , SDL_Rect * clips = NULL )
    {
        SDL_Rect off;
    
        off.x = x;
        off.y = y;
    
        SDL_BlitSurface( get , clips , give , &off );
    }
    
    void clipping()
    {
        clip[0].x = 0;
        clip[0].y = 0;
        clip[0].w = 100;
        clip[0].h = 100;
    
        clip[1].x = 100;
        clip[1].y = 0;
        clip[1].w = 100;
        clip[1].h = 100;
    
        clip[2].x = 0;
        clip[2].y = 100;
        clip[2].w = 100;
        clip[2].h = 100;
    
        clip[3].x = 100;
        clip[3].y = 100;
        clip[3].w = 100;
        clip[3].h = 100;
    
        clip[4].x = 0;
        clip[4].y = 200;
        clip[4].w = 100;
        clip[4].h = 100;
    }
    
    void run( int n , std::string d , int fw , int fh )
    {
        text = TTF_RenderText_Solid( font , d.c_str() , tcolor );
    
        if( text != NULL )
        {
            apply( 0 , 0 , background , screen );
            apply( fw , fh , faces , screen , &clip[n] );
            apply( fw , fh + 100 , text , screen );
        }
    
        SDL_Flip( screen );
    }
    
    int main( int argc , char * args[] )
    {
        bool quit = false;
    
        if( init() == false )
        {
            return 2;
        }
    
        if( loadf() == false )
        {
            return 3;
        }
    
        if( clip != NULL )
        {
            clipping();
        }
    
        run( 0 , "Center!" , 290 , 180 );
    
        while( quit == false )
        {
            while( SDL_PollEvent( &event ) )
            {
                if( event.type == SDL_QUIT )
                {
                    quit = true;
                }
            }
    
            Uint8 * keys = SDL_GetKeyState( NULL );
    
            if( keys[SDLK_UP] )
            {
                run( 1 , "Up!" , 290 , 10 );
    
                if( Mix_PlayChannel( -1 , up , 0 ) == -1 )
                {
                    return 4;
                }
            }
    
            if( keys[SDLK_DOWN] )
            {
                run( 2 , "Down!" , 290 , 340 );
    
                if( Mix_PlayChannel( -1 , down , 0 ) == -1 )
                {
                    return 5;
                }
            }
    
            if( keys[SDLK_LEFT] )
            {
                run( 3 , "Left!" , 10 , 180 );
    
                if( Mix_PlayChannel( -1 , left , 0 ) == -1 )
                {
                    return 6;
                }
            }
    
            if( keys[SDLK_RIGHT] )
            {
                run( 4 , "Right!" , 530 , 180 );
    
                if( Mix_PlayChannel( -1 , right , 0 ) == -1 )
                {
                    return 7;
                }
            }
    
            if( keys[SDLK_SPACE] )
            {
                run( 0 , "Center!" , 290 , 180 );
            }
        }
    
        clean();
    
        return 0;
    }
    Last edited by Kain; 11-24-2012 at 04:55 PM.

  4. #4
    Registered User Kain's Avatar
    Join Date
    Nov 2012
    Posts
    17
    Turns out I can't figure it out it after all.

    Code:
    if( Mix_PlayChannel( -1 , up , 0 ) == -1 ){
    
         return 1;
    
    }
    For some reason in the program on my previous post, Mix_PlayChannel() gives -1, so with the above code the program returns 1.

    But if I remove the "if" segment, and write it like this...

    Code:
    Mix_PlayChannel( -1 , up , 0 );
    ...It works fine, even though some times it plays the sound twice.

    It's just a minor complaint, but it would be nice to know what causes this.

    Thank you in advance.

  5. #5
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    SDL_GetError - SDL Documentation Wiki
    Does this tell you anything, if you call it after the function has returned -1
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  6. #6
    Registered User Kain's Avatar
    Join Date
    Nov 2012
    Posts
    17
    No, it gives nothing.
    The program works fine though if I add "printf( SDL_GetError() );" INSTEAD of "return 1;".
    Generally it works fine if I do not have it return anything if Mix_PlayChannel() gives -1.

  7. #7
    Registered User ledow's Avatar
    Join Date
    Dec 2011
    Posts
    435
    Try moving all your Mix_PlayChannel's into one function that does NOTHING but take an input and play the given sound. And then replace it with just a line of text that prints what sound it thinks it should play. This will help eliminate things like you having to have time to hear the sound, playing "NULL" sounds, etc.

    Compartmentalising your program like this is not only good programming practice but extremely helpful for debugging. I can't see anything at first sight but you call the functions multiple times inside an open loop that's likely to spin very fast so it's hard to tell what might go wrong.

    Also, because of your loop, when it does work it's likely to loop so fast that it will play the sounds and fill every audio channel so long as you have the button down for more than a tiny fraction of a second. It will literally just keep playing the sound again and again while the button is down. Hell, from what I see you could be easily filling all audio channels with a single keypress and that's why Mix_PlayChannel fails. Either adjust your loop to "debounce" your input (i.e. only spot when the changes state, not look for if the key is currently pressed), or use SDL's proper keyboard events (you're already polling the event loop and could easily just check for the event being a key up/down event while you are there).

    But, personally, I'd be pulling out all the PlayChannel's to find your problem and put them into a general purpose function that I would then debug the calling of (e.g. by temporarily replacing or supplementing the actual PlayChannel call inside it with a printf with some helpful information (e.g. the sound file played, the error from PlayChannel for that one, etc.).

    - Compiler warnings are like "Bridge Out Ahead" warnings. DON'T just ignore them.
    - A compiler error is something SO stupid that the compiler genuinely can't carry on with its job. A compiler warning is the compiler saying "Well, that's bloody stupid but if you WANT to ignore me..." and carrying on.
    - The best debugging tool in the world is a bunch of printf()'s for everything important around the bits you think might be wrong.

  8. #8
    Internet Superhero
    Join Date
    Sep 2006
    Location
    Denmark
    Posts
    964
    I noticed your arguments to main are called argc and args, i've had issues with this before. Apparently SDL is picky about this, try renaming it to argv instead of args. I believe this mismatch results in a strange linker error so it's likely not the root of your issues, but worth a shot.
    How I need a drink, alcoholic in nature, after the heavy lectures involving quantum mechanics.

  9. #9
    Registered User rogster001's Avatar
    Join Date
    Aug 2006
    Location
    Liverpool UK
    Posts
    1,472
    use your debug console to track keypresses and calls as suggested above
    Thought for the day:
    "Are you sure your sanity chip is fully screwed in sir?" (Kryten)
    FLTK: "The most fun you can have with your clothes on."

    Stroustrup:
    "If I had thought of it and had some marketing sense every computer and just about any gadget would have had a little 'C++ Inside' sticker on it'"

  10. #10
    Registered User Kain's Avatar
    Join Date
    Nov 2012
    Posts
    17
    Thanks for the suggestions everybody.
    When I find some time I'll try them all, and I'll let you know.
    Thanks again.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Simple program has segmentation fault??
    By fsi in forum C Programming
    Replies: 4
    Last Post: 12-04-2011, 10:25 AM
  2. CS 1 Program segmentation fault but can't see the problem
    By DaNxTh3xMaNx in forum C Programming
    Replies: 1
    Last Post: 09-29-2010, 08:23 PM
  3. srand(time()) returns segmentation fault
    By withoutn in forum C Programming
    Replies: 9
    Last Post: 07-03-2007, 01:59 PM
  4. Segmentation fault on my program
    By blackswan in forum C Programming
    Replies: 2
    Last Post: 05-11-2005, 04:47 PM
  5. Segmentation fault !, program works:S
    By jspri in forum C Programming
    Replies: 8
    Last Post: 09-28-2004, 05:25 PM

Tags for this Thread