SDL_BlitSurface segmentation fault (surfaces aren't null)
        Posted  
        
            by 
                Trollkemada
            
        on Game Development
        
        See other posts from Game Development
        
            or by Trollkemada
        
        
        
        Published on 2012-11-24T12:48:28Z
        Indexed on 
            2012/11/24
            17:19 UTC
        
        
        Read the original article
        Hit count: 398
        
My app is crashing on SDL_BlitSurface() and i can't figure out why. I think it has something to do with my static object. If you read the code you'll why I think so.
This happens when the limits of the map are reached, i.e. (i>width || j>height). This is the code:
Map.cpp (this render)
Tile const * Map::getTyle(int i, int j) const {
    if (i >= 0 && j >= 0 && i < width && j < height) {
        return data[i][j];
    } else {
        return &Tile::ERROR_TYLE;  // This makes SDL_BlitSurface (called later) crash
        //return new Tile(TileType::ERROR); // This works with not problem (but is memory leak, of course)
    }
}
void Map::render(int x, int y, int width, int height) const {
    //DEBUG("(Rendering...) x: "<<x<<", y: "<<y<<", width: "<<width<<", height: "<<height);
    int firstI = x / TileType::PIXEL_PER_TILE;
    int firstJ = y / TileType::PIXEL_PER_TILE;
    int lastI = (x+width) / TileType::PIXEL_PER_TILE;
    int lastJ = (y+height) / TileType::PIXEL_PER_TILE;
    // The previous integer division rounds down when dealing with positive values, but it rounds up
    // negative values. This is a fix for that (We need those values always rounded down)
    if (firstI < 0) {
        firstI--;
    }
    if (firstJ < 0) {
        firstJ--;
    }
    const int firstX = x;
    const int firstY = y;
    SDL_Rect srcRect;
    SDL_Rect dstRect;
    for (int i=firstI; i <= lastI; i++) {
        for (int j=firstJ; j <= lastJ; j++) {
            if (i*TileType::PIXEL_PER_TILE < x) {
                srcRect.x = x % TileType::PIXEL_PER_TILE;
                srcRect.w = TileType::PIXEL_PER_TILE - (x % TileType::PIXEL_PER_TILE);
                dstRect.x = i*TileType::PIXEL_PER_TILE + (x % TileType::PIXEL_PER_TILE) - firstX;
            } else if (i*TileType::PIXEL_PER_TILE >= x + width) {
                srcRect.x = 0;
                srcRect.w = x % TileType::PIXEL_PER_TILE;
                dstRect.x = i*TileType::PIXEL_PER_TILE - firstX;
            } else {
                srcRect.x = 0;
                srcRect.w = TileType::PIXEL_PER_TILE;
                dstRect.x = i*TileType::PIXEL_PER_TILE - firstX;
            }
            if (j*TileType::PIXEL_PER_TILE < y) {
                srcRect.y = 0;
                srcRect.h = TileType::PIXEL_PER_TILE - (y % TileType::PIXEL_PER_TILE);
                dstRect.y = j*TileType::PIXEL_PER_TILE + (y % TileType::PIXEL_PER_TILE) - firstY;
            } else if (j*TileType::PIXEL_PER_TILE >= y + height) {
                srcRect.y = y % TileType::PIXEL_PER_TILE;
                srcRect.h = y % TileType::PIXEL_PER_TILE;
                dstRect.y = j*TileType::PIXEL_PER_TILE - firstY;
            } else {
                srcRect.y = 0;
                srcRect.h = TileType::PIXEL_PER_TILE;
                dstRect.y = j*TileType::PIXEL_PER_TILE - firstY;
            }
            SDL::YtoSDL(dstRect.y, srcRect.h);
            SDL_BlitSurface(getTyle(i,j)->getType()->getSurface(), &srcRect, SDL::getScreen(), &dstRect); // <-- Crash HERE
            /*DEBUG("i = "<<i<<", j = "<<j);
            DEBUG("srcRect.x = "<<srcRect.x<<", srcRect.y = "<<srcRect.y<<", srcRect.w = "<<srcRect.w<<", srcRect.h = "<<srcRect.h);
            DEBUG("dstRect.x = "<<dstRect.x<<", dstRect.y = "<<dstRect.y);*/
        }
    }
}
Tile.h
#ifndef TILE_H
#define TILE_H
#include "TileType.h"
class Tile {
private:
    TileType const * type;
public:
    static const Tile ERROR_TYLE;
    Tile(TileType const * t);
    ~Tile();
    TileType const * getType() const;
};
#endif
Tile.cpp
#include "Tile.h"
const Tile Tile::ERROR_TYLE(TileType::ERROR);
Tile::Tile(TileType const * t) : type(t) {}
Tile::~Tile() {}
TileType const * Tile::getType() const {
    return type;
}
TileType.h
#ifndef TILETYPE_H
#define TILETYPE_H
#include "SDL.h"
#include "DEBUG.h"
class TileType {
protected:
    TileType();
    ~TileType();
public:
    static const int PIXEL_PER_TILE = 30;
    static const TileType * ERROR;
    static const TileType * AIR;
    static const TileType * SOLID;
    virtual SDL_Surface * getSurface() const = 0;
    virtual bool isSolid(int x, int y) const = 0;
};
#endif
ErrorTyle.h
#ifndef ERRORTILE_H
#define ERRORTILE_H
#include "TileType.h"
class ErrorTile : public TileType {
    friend class TileType;
private:
    ErrorTile();
    mutable SDL_Surface * surface;
    static const char * FILE_PATH;
public:
    SDL_Surface * getSurface() const;
    bool isSolid(int x, int y) const ;
};
#endif
ErrorTyle.cpp
(The surface can't be loaded when building the object, because it is a static object and SDL_Init() needs to be called first)
#include "ErrorTile.h"
const char * ErrorTile::FILE_PATH = ("C:\\error.bmp");
ErrorTile::ErrorTile() : TileType(), surface(NULL) {}
SDL_Surface * ErrorTile::getSurface() const {
    if (surface == NULL) {
        if (SDL::isOn()) {
            surface = SDL::loadAndOptimice(ErrorTile::FILE_PATH);
            if (surface->w != TileType::PIXEL_PER_TILE || surface->h != TileType::PIXEL_PER_TILE) {
                WARNING("Bad tile surface size");
            }
        } else {
            ERROR("Trying to load a surface, but SDL is not on");
        }
    }
    if (surface == NULL) { // This if doesn't get called, so surface != NULL
        ERROR("WTF? Can't load surface :\\"); 
    }
    return surface;
}
bool ErrorTile::isSolid(int x, int y) const {
    return true;
}
        © Game Development or respective owner