【问题标题】:Debugging load time error in C++ SDL2 program compiled with VS2015 on Win10在Win10上用VS2015编译的C++ SDL2程序中调试加载时间错误
【发布时间】:2016-10-18 18:41:21
【问题描述】:

我正在使用 Visual Studio 2015 在 64 位 Windows 10 上使用 SDL2 在 C++ 中编写一个项目。我最近购买了一台新的 Windows 10 笔记本电脑并从 github 克隆了我的项目。我的项目编译正确,但运行时出现以下错误:

应用程序无法正确启动 (0xc000007b)。单击“确定”关闭应用程序。

根据我目前的研究,这个错误通常是由加载不兼容的 DLL 引起的,例如64 位版本而不是 32 位版本。到目前为止我发现的建议包括:

  • 检查我使用的是 32 位版本的 SDL2 DLL
  • 安装/重新安装 x86 版本的 Visual C++ Redistributable for Visual Studio 2015
  • 使用Dependency Walker 解决哪个 DLL 出现故障

我的项目设置为为 Win32 构建,并且我确保我使用的是我明确链接的所有 DLL 的 32 位版本(libfreetype-6、libpng16-16、SDL2、SDL2_image、SDL2_mixer、和 SDL2_ttf)。我已经确认我的机器上安装了 x86 VC++ Redistributable。

最后,我尝试使用 Dependency Walker 来确定可能导致问题的 DLL(尽管我已经阅读了 Dependency Walker 有很多误报的警告)。结果如下:

Dependency Walker 静态分析

Dependency Walker 分析结果

在那之后,分析器冻结并且永远不会继续。请注意,SDL 组件和 VC 运行时正在正确加载。

该程序可以在我的两台旧机器上正确编译和加载,一台运行 32 位 Windows 7,另一台运行 64 位 Windows 10。

现在是实际问题。我可以采取哪些其他步骤来调试此崩溃?还是有人从我提供的信息中看出我做错了什么?

相关问题:

编辑:

正如 rflobao 所建议的,我在 32 位 exe 上使用 64 位版本的 Dependency Walker。这是我的分析运行的新输出:

此时,和以前一样,Dependency Walker 冻结。我仍然完全迷失了方向,并且不觉得我更接近能够确定导致问题的原因。

【问题讨论】:

  • Windows 操作系统负责具有匹配名称的searching and finding the first DLL。可能发生的情况是,有一个您可能不知道的 64 位组件位于系统 PATH 中的目录中,而 Windows 碰巧找到了该 DLL 并尝试加载它。
  • 这是有道理的。你知道我有一个系统的方法来确定它是什么吗? Dependency Walker 似乎已经过时而无法使用,当然在我的路径中可以找到数百个 DLL。
  • 在依赖遍历器中,单击 C:\ 图标 - 这将告诉您它从哪里获取文件。您是否尝试过从 64 位 cmd 提示符(windows/system32 中的那个)和 32 位 cmd 提示符(windows/syswow64 中的那个)运行它。
  • 你真的到达主要功能了吗?你在那台机器上安装了 2015 版的 redists 吗?
  • 实际上你的64位exe必须加载一个32位的dll,将所有的dll复制到与exe相同的目录并检查是否有效,并确认每个dll实际上是64位

标签: c++ dll visual-studio-2015 windows-10 sdl-2


【解决方案1】:

我感到非常愚蠢,但我终于弄清楚了真正的问题。我正在使用 SDL 字体库 SDL2_ttf,我只是没有将 zlib.dll 从 SDL2_ttf lib 目录复制到我的构建目录中。我不明白为什么错误消息如此神秘;在过去,缺少的 DLL 给了我一个有用的“foo.dll is missing”错误消息。

无论如何,谢谢大家的帮助。至少我学到了一个有用的教训:在怀疑更复杂的问题之前,始终确保所有必需的 DLL 都存在。

【讨论】:

  • 这也是我的问题!这个问题困扰了我一个多月。显然我在 PATH 的其他地方有另一个 64 位 zlib1.dll 副本,所以我的项目的 64 位版本运行良好。
【解决方案2】:

这绝不是完全可靠的,但您可以尝试一下。它需要 Visual Studio 中包含的 dumpbin.exe。

首先,获取您的程序的依赖 DLL 列表,根据您的路径解析:

del dlls.txt
for /f %d in ('dumpbin /dependents Questless.exe ^| findstr /ic:".dll"') do @echo %~$PATH:d >> dlls.txt

然后得到每个的位数:

for /f "delims=" %d in (dlls.txt) do @echo %d & dumpbin /headers "%d" | findstr /c:"machine (x"

这将产生如下输出:

C:\Windows\System32\kernel32.dll 8664机(x64) C:\programs\ed23\bin\hydra.dll 14C机(x86)

请注意,这错误地使用了 System32 中的 kernel32.dll,而不是 WOW6432,因此它显示为 x64。那是因为它只是使用了路径,当 Windows 加载程序实际上将使用 WOW6432 映射器、SxS、应用程序清单时,并且只有在这些都没有解决依赖关系时才回退到路径上。它也找不到依赖项的依赖项(您可以编写通过依赖项递归的脚本,但一定要过滤掉重复项),当然也不知道有关运行时显式动态加载的任何信息。

尽管如此,这是获取简短列表以进行检查的快速方法,并且可能会发现您的问题。

【讨论】:

  • 这真的很有用!该技术表明 Windows 正在 System32 中查找 64 位版本的 msvcp140d.dll、vcruntime140d.dll、ucrtbased.dll 和 kernel32.dll。是否可以更改一些 Visual Studio 项目设置以使 Windows 在 SysWoW64 中显示 32 位版本?
【解决方案3】:

请注意,Dependency Walker 有 32 位和 64 位版本。如果您的应用程序是 32 位,则应使用 32 位版本。否则,Dependency Walker 将看到 System32 而不是 SisWOW64 的库。 您的图像显示混合了 32 位和 64 位库,其中 64 有错误。

【讨论】:

  • 这确实是我的问题之一。我在我的 32 位可执行文件上使用了 64 位 Dependency Walker。谢谢!用新的输出更新我的问题。
  • 在 Dependency Walker 中“不运行”验证,如果还存在一些 64 位库。如果所有库都是 32 位的,则很可能 libs64 是在惰性模式下动态加载的。确保项目使用的所有库(libfreetype-6、libpng16-16、SDL2、SDL2_image、SDL2_mixer 和 SDL2_ttf,...)都是 32 位编译的。
猜你喜欢
  • 2017-07-07
  • 2015-11-24
  • 2018-08-25
  • 1970-01-01
  • 1970-01-01
  • 2017-01-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多