Segmentation fault from SDL_LowerBlit ()

Started by
3 comments, last by mathall 13 years, 9 months ago
Hi, I'm starting off with C++ and SDL, to help me learn I'm trying to create a small library to make using SDL easier (easy loading of files etc). I'm having a problem blitting to the screen, here is my code for surfaces, the screen and the test program:
//screen.cpp#include "screen.h"#include "surface.h"#include "SDL/SDL.h"#include <iostream>SFrame_Screen::SFrame_Screen(int _width, int _height, int _bpp){    width = _width;    height = _height;    bpp = _bpp;    screen = SDL_SetVideoMode(width, height, bpp, SDL_SWSURFACE);}void SFrame_Screen::blit(int x, int y, SFrame_Surface source, SDL_Rect *clip){    std::cout << screen;    if(source.surface != NULL && screen != NULL){        SDL_Rect offset;        offset.x = x;        offset.y = y;        SDL_BlitSurface(source.surface, clip, screen, &offset);    }}int SFrame_Screen::flip(){     if(screen != NULL){         return SDL_Flip(screen);     }     return -1;}void SFrame_Screen::fill(int r, int g, int B){    SDL_FillRect(screen, &screen->clip_rect, SDL_MapRGB(screen->format, r, g, B));}


//surface.cpp#include <string>#include "surface.h"#include "SDL/SDL.h"#include "SDL/SDL_image.h"#include <iostream>    SFrame_Surface::SFrame_Surface(){    surface = NULL;}SFrame_Surface::SFrame_Surface(SDL_Surface *_surface){    surface = NULL;    surface = _surface;}SFrame_Surface::~SFrame_Surface(){    std::cout << "Freeing surface";    SDL_FreeSurface(surface);}SFrame_Image::SFrame_Image(std::string filename){    SDL_Surface *loadedImage = NULL;    SDL_Surface *optimizedImage = NULL;    loadedImage = IMG_Load(filename.c_str());    if( loadedImage != NULL )    {        optimizedImage = SDL_DisplayFormat(loadedImage);        SDL_FreeSurface(loadedImage);    }    surface = optimizedImage;}void SFrame_Image::set_colour_key(int r, int g, int B){    Uint32 colorkey = SDL_MapRGB(surface->format, r, g, B);    SDL_SetColorKey(surface, SDL_SRCCOLORKEY, colorkey);    }


//test code#include "SDL/SDL.h"#include "SDL/SDL_image.h"#include "sframe.h"#include <string>#include <iostream>const int SCREEN_WIDTH = 640;const int SCREEN_HEIGHT = 480;const int SCREEN_BPP = 32;SDL_Surface *image = NULL;SDL_Event event;SFrame_Screen init(){    SDL_Init( SDL_INIT_EVERYTHING );    SFrame_Screen screen(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP);    SDL_WM_SetCaption( "Test", NULL );    TTF_Init();    return screen;}void clean_up(){    TTF_Quit();    SDL_Quit();}int main( int argc, char* args[] ){    bool quit = false;    if(!sframe_init_everything()){        return 1;    }    SFrame_Screen screen(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP);    SDL_WM_SetCaption( "Test", NULL );        SFrame_Image image("foo.png");    image.set_colour_key(0, 0xFF, 0xFF);    SFrame_Font font("lazy.ttf", 28);    SDL_Color text_colour = { 0, 0, 0 };    SFrame_Surface text = font.render("Hello, world", text_colour);    while( quit == false )    {        while( SDL_PollEvent( &event ) )        {            if( event.type == SDL_QUIT )            {                quit = true;            }        }        screen.fill(255,255,255);        screen.blit(0, 0, image);        screen.blit(300,200,text);        if( screen.flip() == -1 )        {            return 1;        }            }    sframe_clean_up();    return 0;}


When I compile all this and run it the screen comes and then disappears and I get a segmentation fault. I then loaded it with gdb, here's the backtrace:
Program received signal SIGSEGV, Segmentation fault.0x0015df83 in SDL_LowerBlit () from /usr/lib/libSDL-1.2.so.0(gdb) backtrace #0  0x0015df83 in SDL_LowerBlit () from /usr/lib/libSDL-1.2.so.0#1  0x0015e242 in SDL_UpperBlit () from /usr/lib/libSDL-1.2.so.0#2  0x0012f439 in SFrame_Screen::blit (this=0xbffff2d8, x=0, y=0, source=...,     clip=0x0) at screen.cpp:19#3  0x080491ac in main (argc=1, args=0xbffff3e4) at test_sdl.cpp:57

I also ran it through valgrind, it said that a surface's destructor method had been called:
==3789== Invalid read of size 4==3789==    at 0x4076F80: SDL_LowerBlit (in /usr/lib/libSDL-1.2.so.0.11.3)==3789==    by 0x4077241: SDL_UpperBlit (in /usr/lib/libSDL-1.2.so.0.11.3)==3789==    by 0x4047438: SFrame_Screen::blit(int, int, SFrame_Surface, SDL_Rect*) (screen.cpp:19)==3789==    by 0x804914B: main (test_sdl.cpp:57)==3789==  Address 0x492b030 is 48 bytes inside a block of size 60 free'd==3789==    at 0x4024B3A: free (vg_replace_malloc.c:366)==3789==    by 0x4076A15: SDL_FreeSurface (in /usr/lib/libSDL-1.2.so.0.11.3)==3789==    by 0x4047108: SFrame_Surface::~SFrame_Surface() (surface.cpp:18)==3789==    by 0x8049156: main (test_sdl.cpp:57)


Why has it been destroyed and why has it crashed? (All the variables seemed ok...)

EDIT: Full code @ http://filebin.ca/vmkyuy/sdl_framework.zip
Advertisement
In SFrame_Screen::blit(), you are passing the source surface by value. This is a problem since SFrame_Surface doesn't have a proper copy constructor. Pass it by reference, and disallow copy/assignment for SFrame_Surface.

You can do that by declaring the copy constructor and assignment operator as private. You don't even need to implement them:

class SFrame_Surface {private:    SFrame_Surface(const SFrame_Surface &);    const SFrame_Surface & operator=(const SFrame_Surface &);};
Quote:Original post by Gage64
In SFrame_Screen::blit(), you are passing the source surface by value. This is a problem since SFrame_Surface doesn't have a proper copy constructor. Pass it by reference, and disallow copy/assignment for SFrame_Surface.

You can do that by declaring the copy constructor and assignment operator as private. You don't even need to implement them:

*** Source Snippet Removed ***


Thanks for your quick reply. Do you mean pass source.surface by reference:
SDL_BlitSurface(&source.surface, clip, screen, &offset);

? And what should the surface class look like?
class SFrame_Surface {    private:        SFrame_Surface(const SFrame_Surface &);                            const SFrame_Surface & operator=(const SFrame_Surface &);           public:        SFrame_Surface(){};        //SFrame_Surface(SDL_Surface *_surface);        ~SFrame_Surface();                        SDL_Surface *surface;};


Sorry for being such a noob! I better go read up on C/C++ again ;)
I meant that you should change this line:

void SFrame_Screen::blit(int x, int y, SFrame_Surface source, SDL_Rect *clip){

to this:

void SFrame_Screen::blit(int x, int y, SFrame_Surface &source, SDL_Rect *clip){

Notice I added a & before 'source'. This is called a reference and you can read more about it here.
Thanks, and that link really helped!

This topic is closed to new replies.

Advertisement