SDL_image SDL_FreeSurface segfault

I'm not sure which forum this goes in, so I just put this in here. I am making a map renderer for my small (at the moment) game. I loaded an image using SDL_image (IMG_Load) and tried to free it but then it segfaults. It also segfaulted when formatting it. Here is the code:
1
2
3
4
5
6
7
8
SDL_Surface *Load_Image(char *file)
{
	SDL_Surface *sRet=NULL;
	if ((sRet = IMG_Load(file)) == NULL) {
		return NULL;
	}
	return sRet;
}

And function:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
void LoadTiles() {
	SDL_Surface *ts = Load_Image("tileset.gif");
	ifstream file ("map.bin", ios::in|ios::binary|ios::ate);
	if (file.is_open()) {
		ifstream::pos_type size;
		char *fileblock;
		size=file.tellg();
		fileblock = (char*)malloc(size);
		if (fileblock == 0) {
			cerr << "Unable to allocate " << size << " bytes of memory.\n";
			Control::quit=true;
		}
		file.seekg(0, ios::beg);
		file.read(fileblock,size);
		file.close();
		int i;
		for (i=0; i<size; i++) {
			unsigned char tileid=(unsigned char)fileblock[i];
			unsigned int tx = tileid*16;
			unsigned int ty = (int)(tx/ts->w);
			tx = tx % ts->w;
			printf("(%d, %d)\n",tx,ty);
		}
		free(fileblock);
	} else {
		cerr << "Unable to open map.bin.\n";
		Control::quit=true;
	}

	SDL_FreeSurface(ts);
}
I can't see anything wrong with LoadTiles. You said it also segfaults "when formatting it"? Where is that? Is it in the pasted code?


On a side note, your Load_Image function is silly. It's just extra code for doing exactly what IMG_Load does. You might as well just call IMG_Load directly... or shorten Load_Image if you want to keep the possibility of altering the function in the future:

1
2
3
4
5
6
// this code does the exact same thing as your version, only is shorter
//   (and const correct)
SDL_Surface *Load_Image(const char *file)
{
  return IMG_Load(file);
}
The Load_Image function originally had code calling SDL_DisplayFormatAlpha, but that is what caused it to segfault. EDIT: Strange, I recompiled and it worked! EDIT: Recompiled again; it failed. EDIT: I just didn't check the debugger the first time :P Apparently inside the SDL_FreeSurface method it is trying to set the palette to null, but when trying to free it, it has already been freed? Not sure where I could have freed it.
Last edited on
The problem could be somewhere else in the code.
I did a backtrace:
1
2
3
4
5
6
(gdb) backtrace
#0  SDL_SetPixelFormatPalette (format=0x100545e50, palette=0x0) at ../SDL/src/video/SDL_pixels.c:655
#1  0x0000000100099a75 in SDL_FreeSurface (surface=0x100545df0) at ../SDL/src/video/SDL_surface.c:150
#2  0x000000010001069c in LoadTiles () at main.cpp:117
#3  0x0000000100010a61 in main (argc=1, argv=0x7fff5fbff3e8) at main.cpp:137
Current language:  auto; currently c

Where else could the surface be freed?
My new Load_Image function:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
SDL_Surface *Load_Image(char *file)
{
	/*SDL_RWops *src = SDL_RWFromFile(file, "rb");
    char *ext = strrchr(file, '.');
    if(ext) {
        ext++;
    }
    if(!src) {
        /* The error message has been set in SDL_RWFromFile */
	/*
        return NULL;
    }
    return IMG_LoadTyped_RW(src, 0, ext);*/
	return IMG_Load_RW(SDL_RWFromFile(file, "rb"), 0);
}
Last edited on
Do you initialize SDL? Sometimes memory corruption can cause problems that is not noticed until much later in the program. Run your program through valgrind and see what you get.
I did initialize SDL, I'm downloading Valgrind right now.
All I see is a bunch of:
==18805== Signal 11 being dropped from thread 0's queue
messages.
Weird... I recompiled and ran it through valgrind and it didn't segfault. BUT I found Invalid Write and Invalid Reads.
It seems the segfaults are random.
I ran the log through grep and got rid of the "by ..." lines:
1
2
3
4
5
6
7
8
9
10
11
12
==28771== Invalid read of size 4
==28771==    at 0x1000B3A06: SDL_FreeSurface (in /usr/local/lib/libSDL-1.3.0.dylib)
==28771==    at 0x100028679: malloc (vg_replace_malloc.c:266)
==28771== 
==28771== Invalid write of size 4
==28771==    at 0x1000B3A0B: SDL_FreeSurface (in /usr/local/lib/libSDL-1.3.0.dylib)
==28771==    at 0x100028679: malloc (vg_replace_malloc.c:266)
==28771== 
==28771== Invalid read of size 4
==28771==    at 0x1000B18D5: SDL_SetPixelFormatPalette (in /usr/local/lib/libSDL-1.3.0.dylib)
==28771==  Address 0x810000000000434 is not stack'd, malloc'd or (recently) free'd
==28771==  

(And more): malloc is freeing the surface?
Last edited on
bump...
Did you pass the -g flag to gcc (g++)? I think you will get better stack traces if you do that.
Yes, I did.
Here are my makefile lines: (I don't know why there are 2 /'s, but that's what "which sdl-config" said.)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
CC := g++
CFLAGS := `/usr/local/bin//sdl-config --cflags` -g
LFLAGS := `/usr/local/bin//sdl-config --libs` -g -framework OpenGL -framework CoreFoundation -lSOIL -lSDL_image

OBJECTS := main.o control.o

Program: $(OBJECTS)
	$(CC) $(LFLAGS) $(OBJECTS) -o Program

main.o: main.cpp
	$(CC) $(CFLAGS) -c main.cpp -o main.o

control.o: control.cpp
	$(CC) $(CFLAGS) -c control.cpp -o control.o
bump...
I was expecting valgrind to tell what function SDL_FreeSurface was called from.

It is hard to know what the problem is from the code you have posted. If you can provide minimal example that compiles with the problems you describe it will be easier to help.

I also see that you are using SDL 1.3. It is not as stable as SDL 1.2, maybe it has a bug?
Last edited on
1
2
3
4
5
6
7
8
9
10
11
#include <SDL.h>
#include <SDL_image.h>

int main()
{
  SDL_Init(SDL_INIT_VIDEO);
  SDL_SetVideoMode(640,480,32,SDL_OPENGL);
  SDL_FreeSurface(IMG_Load("tileset.png"));
  SDL_Quit();
  return 0;
}

My code has a lot more error checking but this is minimal.
BUMP!
Bump...
That code gives segfault for you?
yes I THINK I compiled SDL_Image incorrectly
Last edited on
Topic archived. No new replies allowed.