I have to create an OCR in C using SDL2 and SLD2_image.
Everything works fine on macOS. However, when running my program on Linux I get a segfault when saving the PNG file.
I tried to update the libraries I use (SDL2, SDL2_image and libpng) and was only able to save a black image and get a segfault on IMG_QUIT() or SDL_QUIT()
So my code crashes at IMG_SavePNG(surface, "textmono.png")
I also tried
SDL_SaveBMP(surface, "textmono.bmp")
And got the same result...
So here is my code:
void BlackAndWhite(SDL_Surface* surface){
Uint32 *pixels = (Uint32 *)surface->pixels;
for(int i = 0; i < surface->h; i++){
for(int j = 0; j < surface->w;j++){
Uint8 red = 0;
Uint8 green = 0;
Uint8 blue = 0;
SDL_GetRGB(pixels[i*surface->w + j], surface->format, &red, &green, &blue);
Uint8 black = (red + green + blue)/3;
pixels[i*surface->w + j] = SDL_MapRGB(surface->format, black, black, black);
}
}
IMG_SavePNG(surface, "textbw.png");
}
And here is how i load my png file:
int loadimage(void){
if(SDL_Init(SDL_INIT_VIDEO)==-1)
{
printf("SDL_Init: %s\n", SDL_GetError());
return 1;
}
IMG_Init(~0);
SDL_Surface *surface = IMG_Load("text.png");
if(surface != NULL){
...
}
else{
printf("Failed ! %s\n", IMG_GetError());
}
return 0;
}
GDB gives me this:
Thread 1 "main" received signal SIGSEGV, Segmentation fault.
0x00007ffff7cc947d in _int_malloc (av=av@entry=0x7ffff7e16c40 <main_arena>,
bytes=bytes@entry=1304) at malloc.c:3880
3880 malloc.c: Aucun fichier ou dossier de ce type.
(gdb) where
0x00007ffff7cc947d in _int_malloc (
av=av@entry=0x7ffff7e16c40 <main_arena>, bytes=bytes@entry=1304)
at malloc.c:3880
0x00007ffff7ccacaa in __GI___libc_malloc (bytes=1304) at malloc.c:3073
0x00007ffff3894e74 in png_malloc_warn ()
from /lib/x86_64-linux-gnu/libpng16.so.16
0x00007ffff388ec41 in ?? () from /lib/x86_64-linux-gnu/libpng16.so.16
0x00007ffff38ab88e in png_create_write_struct_2 ()
from /lib/x86_64-linux-gnu/libpng16.so.16
0x00007ffff38ab931 in png_create_write_struct ()
from /lib/x86_64-linux-gnu/libpng16.so.16
0x00007ffff7e47d88 in IMG_SavePNG_RW_libpng (surface=0x5555558c9f00,
dst=0x5555557fca40, freedst=1) at IMG_png.c:544
0x000055555555531f in BlackAndWhite (surface=0x5555558c9f00) at main.c:60
0x00005555555554d0 in loadimage () at main.c:38
0x0000555555555116 in main () at main.c:21
EDIT: AddressSanitizer tells me, that there is a heap-buffer-overflow at
SDL_GetRGB(pixels[i*surface->w + j], surface->format, &red, &green, &blue)
Removing this part of the code does solve the problem, so I guess I found the problem, but I don't really get what is wrong with this line...
GDB gives me this:
Any crash inside malloc
or free
usually (99.9% of time) means that you have heap corruption (such as, overflowing heap-allocated memory, free
ing something twice, free
ing unallocated memory, etc. etc.).
Such bugs are quite hard to find, especially when you use 3-rd party libraries and don't understand their requirements well.
Fortunately, there are tools which make finding and understanding such bugs much easier: Valgrind and address sanitizer.
Use one of them, and the bug will likely be obvious. If it's not, you can edit your question with the output from the tool you used, and you will likely get a better answer.