【问题标题】:libpng 1.616 crashing on png_read_png in VS2012 C++libpng 1.616 在 VS2012 C++ 中的 png_read_png 上崩溃
【发布时间】:2015-05-26 08:37:00
【问题描述】:

我是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 中构建的,还是我的 VS2012 项目不喜欢的 VS2010 构建库中有一些命令行/编译器设置是否会有所不同。我已经阅读了 png 文档并在网上搜索了几个小时,但似乎找不到任何相关的东西。任何形式的帮助、提示、指示或建议都会对我有很大帮助。

【问题讨论】:

  • 我打赌你的png_ptrNULL。可以用调试器什么的吗?
  • 导致崩溃的不是我的项目,而是 PNG 库。当我将它链接到我的 VS2010 项目时,这个库工作正常,但当我将它链接到我的 VS2012 项目时崩溃。我使用相同的路径/s 和库来链接和构建,使用相同的运行时库构建约定,并使用相同的方法来读取和创建用于渲染的 png 纹理。在调用 png_read_png() 之前,libpng 还使用了其他函数,它们会打开并验证该文件是否为有效的 PNG 文件。
  • 我不是在寻找责备。我只是说这个指针很可能是NULL
  • 我明白了,非常感谢您的回复。

标签: c++ visual-studio-2012 access-violation libpng first-chance-exception


【解决方案1】:

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

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

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

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

1) 不要将 libpng 和 zlib 都构建到单独的 DLL 中;将 libpng DLL 链接到静态 zlib(这是 projects/vstudio 所做的)或在项目中使用静态 libpng(不是 DLL)(projects/vstudio 也构建其中之一。)

2) 阅读各种 Visual Studio 运行时。您运行的所有内容都必须使用完全相同的运行时;检查每个项目以查看它具有的运行时。最好使用默认值(/MD)

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

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

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

约翰·鲍勒

【讨论】:

  • 我从他们的网站下载了最新的 libpng 压缩文件。然后我将其内容提取到选择的指定文件夹中。之后,我将最新版本的 zlib 下载为 zip 文件,并将其内容提取到与 libpng 相同的根文件夹中。然后我进入 libpng 的目录并打开它的解决方案。在尝试以调试或发布模式构建库之前,我打开了 libpng 附带的 zlib props 文件,以确保 zlib 的正确路径/版本位于 props(xml) 文件中。默认情况下,路径和版本匹配...
  • libpng 项目设置为 zlib 设置了依赖项,并且自动设置了构建顺序。如果需要,我在 libpng 中唯一更改的是运行时库设置(如果需要)。根据您上面所说的,我会考虑到这一点并重新考虑。我可能会尝试采用 libpng 默认解决方案并尝试使用 VS2012 打开它并在那里构建它而不是 VS2010。
  • 然后你有一个正确链接的 libpng DLL,我假设使用了“发布 DLL”。这会运行一组检查以确保 DLL 实际工作,我假设它们都通过了。
  • 因此您需要检查项目运行时设置是否有任何调用“fopen”;我知道你打电话给 png_init_io 因为否则 fread 不会被调用。我怀疑你会发现崩溃的项目不知何故是针对默认 (/MD) 以外的运行时构建的;可能是 /MT(发布多线程)。非常很难做到这一点,更改设置似乎并不总是会导致重建。
  • 感谢您的反馈。这是非常有见地的,你的反应很接近。阅读您的答案并再次查看 libpng 和我的项目后;我知道问题不在于运行时,因为该库在我的 VS2010 项目中工作。你确实帮助引导我解决问题。我在自己的回答中描述了它。它与构建库的 VS 版本以及您要链接的项目所构建的 VS 版本有关。如果在 VS10 中创建项目,则在 VS2010 中构建库,如果在 VS2012 或 VS2013 中,则在 VS2012 或 VS2013 中构建库。
【解决方案2】:

经过相当多小时的试验和错误,并在其他人的一点点帮助下,我终于能够使用相同版本的 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' 解决方案。构建发布和调试。

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

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

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

因此,总而言之,如果您使用的是可以从网络下载的外部库,该库附带您需要打开并构建自己以链接的解决方案,并且您需要相同的库用于跨不同版本 Visual Studio 的项目那么您将不得不在您计划与当前项目一起使用的同一版本的 Visual Studio 中打开该库附带的解决方案。我希望我自己的情况能够作为其他人的答案!

【讨论】:

    【解决方案3】:

    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");
    }
    

    它对我有用。 闻起来很糟糕,但没关系

    另外,优点是它适用于调试版和发布版

    【讨论】:

      猜你喜欢
      • 2014-05-11
      • 2018-11-06
      • 1970-01-01
      • 1970-01-01
      • 2014-03-01
      • 1970-01-01
      • 2015-01-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多