-1

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

genpfault
  • 51,148
  • 11
  • 85
  • 139
  • 1
    The crash happens at line 60 in the file main.c, which is in the function `BlackAndWhite` which you do not show us. – Some programmer dude Oct 05 '19 at 09:42
  • My bad, I removed BlackAndWhite to see if it would solve the problem, It did not the error is the same. The only difference between BlackAndWhite and MonoColor is that BlackAndWhite makes a grayscale image,Anyway, I'm going to replace the code in the question. Thanks for your answer – Pierre Pelletier Oct 05 '19 at 10:11
  • update: It "works" (There is some strange horitonzal lines on the picture but it does not crash) with "lena.png" from the SDL_image documentation, maybe because the picture is 512x512, – Pierre Pelletier Oct 05 '19 at 11:00
  • 1
    Please take some time to read about [how to ask good questions](http://stackoverflow.com/help/how-to-ask), as well as [this question checklist](https://codeblog.jonskeet.uk/2012/11/24/stack-overflow-question-checklist/). And please learn how to create a [mcve] to show us, preferably one that we can copy-paste and try ourselves to replicate your crash. – Some programmer dude Oct 05 '19 at 13:57

2 Answers2

0

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, freeing something twice, freeing 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.

Employed Russian
  • 199,314
  • 34
  • 295
  • 362
0

Okay, so I used an other way of getting and setting pixels, and everything seems to work now... My code now looks like this:

void BlackAndWhite(SDL_Surface* surface){
    int i = 0;
    int j = 0;
    for(i = 0; i < surface->h; i++){
        for(j = 0; j < surface->w;j++){
            Uint8 red = 0;
            Uint8 green = 0;
            Uint8 blue = 0;
            Uint32 pixel = getpixel(surface,j,i);
            SDL_GetRGB(pixel, surface->format, &red, &green, &blue);
            Uint8 black = (red + green + blue)/3;
            pixel = SDL_MapRGB(surface->format, black, black, black);
            putpixel(surface,j,i,pixel);
        }
    }
    IMG_SavePNG(surface, "textbw.png");
}
putpixel 

and

getpixel 

beeing the corresponding functions on this page: Pixel Access - SDL