libpng 1.616在VS2012 C++中的png_read_png上崩溃

libpng 1.616 crashing on png_read_png in VS2012 C++

本文关键字:png read 崩溃 中的 C++ VS2012 libpng      更新时间:2023-10-16

我使用的是win7 64位家庭版。我的所有项目都设置为使用C++在32位环境中构建。我已经使用MDd运行时在调试模式下成功地构建了libpng。我有两个正在进行的项目。我的第一个项目是在VS2010,第二个是在VS2012。在我的计算机中,我创建了一个环境变量,设置为该库的路径,以使链接在我的项目中更容易。我的两个项目都使用MDd和多字节,这与libpng使用的相同。我的所有路径和依赖项都是正确的。我还将libpng16.dll复制到两个项目中,并将其作为构建的可执行文件复制到同一目录中。我可以成功地编译和构建这两个项目。我的VS2010项目运行并渲染加载的PNG图形,但我在VS2012中的项目没有。当我调用png_read_png抛出并在以下行中断的未处理异常时,它崩溃了:

check = fread( data, 1, length, png_voidcast( png_FILE_p, png_ptr->io_ptr ) );

在pngrio.c.中给出此错误:

First-chance exception at 0x77308E19 (ntdll.dll) in Game_debug.exe: 0xC0000005: 
Access violation writing location 0x00000014.

这个问题不在我的源代码中,因为我知道它在我的VS2010项目中有效,并且我正在使用相同的实现来加载我的VS2012项目中的png。我不确定我链接到的库是否是在VS2010中构建的,或者VS2010构建的库中是否有我的VS2012项目不喜欢的一些命令行/编译器设置。我已经阅读了png文档,在网上搜索了几个小时,似乎找不到任何相关的内容。任何形式的帮助、提示、指点或建议都会对我大有裨益。

阅读libpng源代码中的projects/vstudio/readme.txt文件,特别是第41行开始的段落。

您正在向libpng传递一个(FILE*),可能使用png_init_io。Visual Studio在尝试访问底层FILE结构时在fread内部崩溃。

这是因为您使用fopen从一个Visual Studio运行时创建了FILE*,但libpng链接到不同的Visual Studio运行库(msvcrt或类似的东西);这两个运行时是不兼容的。

有很多方法可以导致这种情况发生,但如果使用zlib DLL,几乎肯定会发生。你是使用projects/vstudio来构建libpng,还是自己尝试过?如果你没有使用projects/vstudio,你就只能靠自己了;-)

1) 不要将libpng和zlib都构建到单独的DLL中;将libpng DLL链接到静态zlib(projects/vstudio就是这样做的),或者在项目中使用静态libpng(而不是DLL)(projects/vs.tudio也构建其中一个。)

2) 阅读各种Visual Studio运行时。运行的所有程序都必须使用完全相同的运行时;检查每个项目,看看它有什么运行时。最好使用默认(/MD)

3) 如果您认为在libpng中遇到了错误,请静态链接您的应用程序(即不要使用Visual Studio构建的任何DLL),然后重试。Windows DLL很好;是VisualStudio使用VisualStudio运行时破坏了一切。

4) 如果静态链接时出现问题,请确保DEBUG设置在任何地方都是相同的。您不能混合"最大DEBUG",因为MSVC运行时的调试版本(其中任何一个,甚至在Visual Studio之前)与发布版本不兼容。

事实上,最好不要使用png_init_io;libpng支持这一点。提供您自己的读写回调。可以安全地在这些(fread)中使用stdio,因为它们与fopen调用是在同一个DLL(您编写的DLL)中实现的。只要你不通过DLL边界传递(FILE*),你就应该是安全的;从来没有人解释或理解过两个DLL(zlib,libpng)的行为。

John Bowler

经过数小时的尝试和错误,在其他人的帮助下,我终于能够使用相同版本的libpng成功构建我的2012项目。我要做的是在libpng所在的目录中创建3个文件夹

  1. VS2010\lpng1616\,VS2010\zlib-1.2.8
  2. VS2012\lpng1616\,VS2012\zlib-1.2.8
  3. VS2013\lpng1616\,VS2013\zlib-1.2.8

在这3个文件夹中的每一个文件夹中,我都必须在受尊重的Visual Studio版本中打开libpng的解决方案。构建发布和调试。

然后在我的计算机上为环境变量创建了3个,而不是一个。

  1. PNG_SDK_2010设置为VS2010\lpng1616\
  2. PNG_SDK_2012"VS2012\lpng1616\
  3. PNG_SDK_2013"VS2013\lpng1616\

然后回到我的VS2010和VS2012项目中,使用环境变量设置路径,相应地用新建的库替换旧的过时库,清理了解决方案,两个项目都能正常工作!

因此,总之,如果您使用的是外部库,您可以从网络上下载该库,该库附带了一个解决方案,您需要打开该解决方案并自行构建以进行链接,并且跨不同版本的Visual Studio的项目需要该库,则您必须在您计划的同一版本的Visual Studio中打开该库附带的解决方案与当前项目一起使用。我希望我自己的处境能成为别人的答案!

刚刚在libpng和curl方面遇到了同样的问题lib和curl都使用"msvcrt.dll"所以我只是添加了讨厌的变通方法

HMODULE h = LoadLibraryA("msvcrt.dll");
typedef FILE * (*FP)(char *f, char *m);
FP myf = (FP)GetProcAddress(h, "fopen");
if (myf)
{
    fp = myf((char *)lpszFileName, "wb");
}

这对我很有效。闻起来很臭,但不管

Slso的优点是它适用于调试和发布版本