0
votes

I am trying to create an SDL_Texture using SDL_CreateTextureFromSurface. I have successfully implemented this function multiple times without issue. Currently I am getting the following backtrace information:

#0  0xb7ef1e80 in ?? () from /usr/lib/libSDL2-2.0.so.0
#1  0xb7edf19c in ?? () from /usr/lib/libSDL2-2.0.so.0
#2  0xb7f12e1d in ?? () from /usr/lib/libSDL2-2.0.so.0
#3  0xb7f13ee7 in ?? () from /usr/lib/libSDL2-2.0.so.0
#4  0xb7eb2c08 in ?? () from /usr/lib/libSDL2-2.0.so.0
#5  0xb7e9f474 in SDL_CreateTextureFromSurface () from /usr/lib/libSDL2-2.0.so.0
#6  0x0805999e in Building::draw (this=0xbfffe9a8, Render=@0xbffff6d8: 0x81bd1b8)
    at /code/directory/LIBRARY.h:194
#7  0x08063df7 in main (argc=1, args=0xbffffac4) at Program.cpp:1151

The only thing different between the rest of my code and this particular implementation is that my SDL_Surface is a pointer array defined as follows:

//<Initialize window and renderer (not included here)>
SDL_Surface** Surf;
SDL_Surface* SomeOtherSurface;
int SurfSize = 0;

SomeOtherSurface = LoadBMP("Filename.bmp");
for (i = 0; i < 2; i++)
{
    Surf = (SDL_Surface**) realloc(Surf,SurfSize+1)*sizeof(SDL_Surface*));

    SDL_LockSurface(SomeOtherSurface);
    Surf[i] = SDL_CreateRGBSurfaceFrom(SomeOtherSurface->pixels,SomeOtherSurface->w,SomeOtherSurface->h,32,SomeOtherSurface->pitch,0xFF000000,0x00FF0000,0x0000FF00,0x000000FF); //Create a surface in Surf based on SomeOtherSurface
    SDL_UnlockSurface(SomeOtherSurface);
    SurfSize++;
}
SDL_FreeSurface(SomeOtherSurface);
SDL_Texture* Tex1;
Tex1 = SDL_CreateTextureFromSurface(Render,Surf[0]); //Create the texture; this throws the SIGSEGV

I've written a similar code elsewhere in the program and it hasn't failed; can anyone figure out what's going wrong here? The error would seem to suggest a problem with the memory, but if I try to access Surf[0]->w it returns values as expected.

EDIT: Some additional info which could help solve this: In my code, I free the 'SomeOtherSurface' surface prior to defining the texture. If I define the texture prior to freeing the surface, everything works fine. Is it possible that the two surfaces are sharing the pixel data address?

SOLVED: I need to use SDL_BlitSurface to copy the data and modify it. If I then proceed to free the surface after using SDL_CreateRGBSurfaceFrom then the existing pixel data is also deleted resulting in a segfault when the program tries to access that memory address.

1
In your actual code, are you initialising Surf as a null pointer before the first realloc()? The realloc() call you present here wouldn't compile (extra closing parenthesis at the end) but you might want to double-check you aren't actually multiplying the pointer returned from realloc() by the size of a pointer... - notmyfriend
yes, I missed an open bracket there. Surf is not initialised as null before realloc. - Arlington
Well.. you should definitely be initialising it to null before the first call to realloc. Otherwise, if the memory location happens to contain something other than 0, realloc()'s behaviour is undefined since the pointer passed must have been returned by an earlier call to malloc(), calloc() or realloc(). - notmyfriend
Also since you tagged this C++, any particular reason why you're not just using a std::vector of pointers? - notmyfriend
Tried initializing to NULL; same error (still occurs in the SDL_CreateTextureFromSurface call). Also, I just don't like doing vectors of pointers. I might try it later, but for now I prefer realloc because I have more experience with it. - Arlington

1 Answers

1
votes

The issue with this code is that SDL_CreateRGBSurfaceFrom uses existing pixel data; thus, when you call an SDL_FreeSurface, the pixel data gets lost. Now, Surf[i] tries to find that pixel data when calling SDL_CreateTextureFromSurface and the memory is not accessible.

Solution: using an SDL_BlitSurface to make a copy of the pixel data for further use.