Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/159.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ libpng在png_read_info()上崩溃_C++_Access Violation_Libpng - Fatal编程技术网

C++ libpng在png_read_info()上崩溃

C++ libpng在png_read_info()上崩溃,c++,access-violation,libpng,C++,Access Violation,Libpng,我正在尝试在vs2013中使用libpng 1.2.10读取png文件。我下载了最新的zlib并编译了pnglib,效果很好。现在我正在尝试加载一个文件: int *w = &width; int *h = &height; const char* name = file.c_str(); FILE *png_file = fopen(name, "rb"); if (!png_file) { std::cerr << "Could not open " +

我正在尝试在vs2013中使用libpng 1.2.10读取png文件。我下载了最新的zlib并编译了pnglib,效果很好。现在我正在尝试加载一个文件:

int *w = &width;
int *h = &height;
const char* name = file.c_str();
FILE *png_file = fopen(name, "rb");
if (!png_file)
{
    std::cerr << "Could not open " + file << std::endl;
    return;
}

unsigned char header[PNG_SIG_BYTES];

fread(header, 1, PNG_SIG_BYTES, png_file);
if (png_sig_cmp(header, 0, PNG_SIG_BYTES))
{
    std::cerr << "PNG signature fail " + file << std::endl;
    return;
}

png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if(png_ptr == NULL)
{
    std::cerr << "PNG read fail " + file << std::endl;
    return;
}
png_infop info_ptr = png_create_info_struct(png_ptr);
if(!info_ptr)
{
    std::cerr << "PNG info fail " + file << std::endl;
    return;
}
png_infop end_info = png_create_info_struct(png_ptr);
if(!end_info)
{
    std::cerr << "PNG info end fail " + file << std::endl;
    return;
}
if (setjmp(png_jmpbuf(png_ptr)))
{
    std::cerr << "PNG setjmp fail " + file << std::endl;
    return;
}
png_init_io(png_ptr, png_file);
png_set_sig_bytes(png_ptr, PNG_SIG_BYTES);
png_read_info(png_ptr, info_ptr);

*w = png_get_image_width(png_ptr, info_ptr);
*h = png_get_image_height(png_ptr, info_ptr);

png_uint_32 bit_depth, color_type;
bit_depth = png_get_bit_depth(png_ptr, info_ptr);
color_type = png_get_color_type(png_ptr, info_ptr);

if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
{
    std::cerr << "Grayscale PNG not supported " + file << std::endl;
    return;
}

if (bit_depth == 16)
    png_set_strip_16(png_ptr);

if (color_type == PNG_COLOR_TYPE_PALETTE)
    png_set_palette_to_rgb(png_ptr);
else if (color_type == PNG_COLOR_TYPE_GRAY ||
    color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
{
    png_set_gray_to_rgb(png_ptr);
}

if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
    png_set_tRNS_to_alpha(png_ptr);
else
    png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);

png_read_update_info(png_ptr, info_ptr);

png_uint_32 rowbytes = png_get_rowbytes(png_ptr, info_ptr);
png_uint_32 numbytes = rowbytes*(height);
png_byte* pixels = (png_byte*)malloc(numbytes);
png_byte** row_ptrs = (png_byte**)malloc((height)* sizeof(png_byte*));

int i;
for (i = 0; i<height; i++)
    row_ptrs[i] = pixels + (height - 1 - i)*rowbytes;

png_read_image(png_ptr, row_ptrs);

free(row_ptrs);
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
fclose(png_file);

//return (char *)pixels;

Create(*w, *h, 4, pixels, GL_UNSIGNED_BYTE);
具体而言,错误发生在以下位置:

#ifdef PNG_STDIO_SUPPORTED
/* This is the function that does the actual reading of data.  If you are
 * not reading from a standard C stream, you should create a replacement
 * read_data function and use it at run time with png_set_read_fn(), rather
 * than changing the library.
 */
void PNGCBAPI
png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
{
   png_size_t check;

   if (png_ptr == NULL)
      return;

   /* fread() returns 0 on error, so it is OK to store this in a png_size_t
    * instead of an int, which is what fread() actually returns.
    */
   check = fread(data, 1, length, png_voidcast(png_FILE_p, png_ptr->io_ptr)); // <---------- ERROR HERE

   if (check != length)
      png_error(png_ptr, "Read Error");
}
#endif
#支持ifdef PNG#u STDIO#u
/*这是用于实际读取数据的函数。如果你是
*不从标准C流读取,您应该创建一个替换
*读取数据函数,并在运行时与png\u set\u read\u fn()一起使用,而不是
*而不是改变图书馆。
*/
无效PNGCBAPI
png_默认_读取_数据(png_结构png_ptr、png_字节数据、png_大小长度)
{
png尺寸检查;
如果(png_ptr==NULL)
返回;
/*fread()在出现错误时返回0,因此可以将其存储在png大小中
*而不是实际返回的int。
*/

check=fread(data,1,length,png_voidcast(png_FILE_p,png_ptr->io_ptr));//这是由于libpng和项目之间的编译器设置不匹配造成的。特别是运行时库设置,在libpng和项目中都必须是多线程DLL(/MD)。自述文件说明:

如果不使用VisualStudio默认值,则仍必须构建应用程序 使用默认的运行时选项(/MD)。如果由于某种原因,它不是您的 libpng尝试读取时,应用程序将在libpng16.dll内崩溃 从您传入的文件句柄

避免崩溃和保留调试可能性的最简单方法是在项目中复制“Release”配置,并更改一些属性,以便您可以在Visual Studio中轻松调试。下面介绍如何执行此操作:

  • 单击项目->属性->配置管理器->展开活动解决方案配置,然后单击。选择一个新名称并从发布中复制设置
  • 现在,在项目设置中,选择新创建的配置并更改以下属性:
    • C/C++->General->调试信息格式:用于编辑和继续的程序数据库(/ZI)
    • C/C++->优化->优化:禁用(/Od),整个程序优化:否
    • 这就是所有必要的。您还可以禁用链接器优化(引用和COMDAT折叠),启用最小重建,等等

  • 就这样,祝你好运!

    libpng-1.2.10?哇,这太古老了(2006年4月)。传统libpng-1.2分支中的当前版本是1.2.51。你可以尝试使用1.2.51或1.6.10构建吗?装饰“PNGCBAPI”直到libpng-1.5.0才出现,因此你不能查看libpng-1.2.10。
    #ifdef PNG_STDIO_SUPPORTED
    /* This is the function that does the actual reading of data.  If you are
     * not reading from a standard C stream, you should create a replacement
     * read_data function and use it at run time with png_set_read_fn(), rather
     * than changing the library.
     */
    void PNGCBAPI
    png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
    {
       png_size_t check;
    
       if (png_ptr == NULL)
          return;
    
       /* fread() returns 0 on error, so it is OK to store this in a png_size_t
        * instead of an int, which is what fread() actually returns.
        */
       check = fread(data, 1, length, png_voidcast(png_FILE_p, png_ptr->io_ptr)); // <---------- ERROR HERE
    
       if (check != length)
          png_error(png_ptr, "Read Error");
    }
    #endif