//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