使用 SDL_image 保存 PNG 时出现段错误
Segfault when saving PNG with SDL_image
我必须使用 SDL2 和 SLD2_image 在 C 中创建 OCR。
在 macOS 上一切正常。但是,当 运行 我的程序在 Linux 上时,我在保存 PNG 文件时遇到段错误。
我尝试更新我使用的库(SDL2、SDL2_image 和 libpng),但只能保存黑色图像并在 IMG_QUIT() 或 [=44= 上出现段错误]()
所以我的代码在 IMG_SavePNG(surface, "textmono.png")
崩溃了
我也试过了
SDL_SaveBMP(surface, "textmono.bmp")
得到了同样的结果...
这是我的代码:
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");
}
这是我加载 png 文件的方式:
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 给我这个:
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
编辑:AddressSanitizer 告诉我,
处存在堆缓冲区溢出
SDL_GetRGB(pixels[i*surface->w + j], surface->format, &red, &green, &blue)
删除这部分代码确实解决了问题,所以我想我发现了问题,但我真的不明白这一行有什么问题...
GDB gives me this:
任何 inside malloc
或 free
通常(99.9% 的时间)的崩溃意味着您有堆损坏(例如,堆分配溢出内存,free
ing 两次,free
ing 未分配的内存,等等)。
这样的 bug 很难找到,尤其是当你使用 3-rd 方库并且不太了解它们的要求时。
幸运的是,有一些工具可以让查找和理解此类错误 容易得多:Valgrind and address sanitizer.
使用其中之一,错误可能会很明显。如果不是,您可以使用您使用的工具的输出编辑您的问题,您可能会得到更好的答案。
好的,所以我使用了另一种获取和设置像素的方法,现在一切似乎都正常了...我的代码现在如下所示:
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
和
getpixel
查看本页相应功能:
Pixel Access - SDL
我必须使用 SDL2 和 SLD2_image 在 C 中创建 OCR。
在 macOS 上一切正常。但是,当 运行 我的程序在 Linux 上时,我在保存 PNG 文件时遇到段错误。
我尝试更新我使用的库(SDL2、SDL2_image 和 libpng),但只能保存黑色图像并在 IMG_QUIT() 或 [=44= 上出现段错误]()
所以我的代码在 IMG_SavePNG(surface, "textmono.png")
我也试过了
SDL_SaveBMP(surface, "textmono.bmp")
得到了同样的结果...
这是我的代码:
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");
}
这是我加载 png 文件的方式:
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 给我这个:
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
编辑:AddressSanitizer 告诉我,
处存在堆缓冲区溢出SDL_GetRGB(pixels[i*surface->w + j], surface->format, &red, &green, &blue)
删除这部分代码确实解决了问题,所以我想我发现了问题,但我真的不明白这一行有什么问题...
GDB gives me this:
任何 inside malloc
或 free
通常(99.9% 的时间)的崩溃意味着您有堆损坏(例如,堆分配溢出内存,free
ing 两次,free
ing 未分配的内存,等等)。
这样的 bug 很难找到,尤其是当你使用 3-rd 方库并且不太了解它们的要求时。
幸运的是,有一些工具可以让查找和理解此类错误 容易得多:Valgrind and address sanitizer.
使用其中之一,错误可能会很明显。如果不是,您可以使用您使用的工具的输出编辑您的问题,您可能会得到更好的答案。
好的,所以我使用了另一种获取和设置像素的方法,现在一切似乎都正常了...我的代码现在如下所示:
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
和
getpixel
查看本页相应功能: Pixel Access - SDL