在Win10上使用VS2015编译的C++ SDL2程序中调试加载时间错误

10

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

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

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

  • 检查我是否使用32位版本的SDL2 DLL
  • 安装/重新安装Visual Studio 2015的x86版本Visual C++ Redistributable
  • 使用Dependency Walker来排除故障的DLL

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

最后,我尝试使用Dependency Walker确定可能导致问题的DLL(虽然我已经阅读了对依赖项Walker有很多误报的警告)。以下是结果:

Dependency Walker静态分析 Dependency Walker static analysis

Dependency Walker分析结果 Dependency Walker profiling results

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

这个程序在我的两台旧电脑上编译和加载都正确,在一台运行32位Windows 7,另一台运行64位Windows 10。

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

相关问题:

编辑:

如rflobao建议的那样,我正在使用64位版本的Dependency Walker对32位exe进行分析。这是我的新分析结果:

New Dependency Walker Profile Output

到目前为止,与以前一样,Dependency Walker会卡住。我仍然一筹莫展,感觉离确定问题的原因更远了。


1
Windows操作系统负责搜索并找到第一个具有匹配名称的DLL。可能发生的情况是,您可能不知道存在于系统路径中的目录中的64位组件,而Windows恰好找到该DLL并尝试加载它。 - PaulMcKenzie
那很有道理。你知不知道有没有一种系统的方法可以确定是哪一个呢?Dependency Walker似乎过时了,也有成百上千的DLL可以在我的路径中找到。 - Jonathan Sharman
在依赖项查找器中,单击C:\图标 - 这将告诉您它正在从哪里获取文件。您是否尝试从64位cmd提示符(位于windows/system32)和32位cmd提示符(位于windows/syswow64)运行它? - cup
你是否真正到达了主函数?你在那台机器上安装了2015 redists吗? - paulm
实际上,你的64位exe必须加载一个32位dll,将所有的dll复制到与exe相同的目录中,并检查是否可以正常工作,还要确认每个dll实际上都是64位。 - paulm
3个回答

5
请注意,Dependency Walker有32位和64位版本。如果您的应用程序是32位的,您应该使用32位版本。否则,Dependency Walker将查看System32而不是SisWOW64中的库文件。 您的图片显示了32位和64位库文件混合在一起,其中64位存在错误。

那确实是我的问题之一。我在32位可执行文件上使用了64位依赖项查看器。谢谢!我会用新的输出更新我的问题。 - Jonathan Sharman
在不运行程序的情况下,在Dependency Walker中验证是否存在某些64位库。 如果所有库都是32位的,则很可能libs64以惰性模式动态加载。 确保您的项目使用的所有库(libfreetype-6、libpng16-16、SDL2、SDL2_image、SDL2_mixer和SDL2_ttf等)都是32位编译的。 - rflobao

4
这并不是完全可靠的方法,但你可以试一试。它需要使用dumpbin.exe,该程序已包含在Visual Studio中。
首先,获取程序依赖的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中的kernel32.dll,因此显示为x64。这是因为它只使用了路径,而Windows加载程序实际上会使用WOW6432映射器、SxS、应用程序清单,并仅在这些都未解析依赖项时回退到路径。它也不会找到依赖于依赖项的内容(您可以编写递归遍历依赖项的脚本,但务必过滤掉重复项),当然不知道任何关于运行时显式动态加载的内容。
尽管如此,这是一种快速获取简短列表并检查问题的方法,可能会确定您的问题。

这真的很有用!这种技术表明Windows正在System32中查找msvcp140d.dll、vcruntime140d.dll、ucrtbased.dll和kernel32.dll的64位版本。是否有一些Visual Studio项目设置我可以更改,使Windows在SysWoW64中查找32位版本呢? - Jonathan Sharman

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

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


1
这也是我的问题!这个问题困扰了我一个多月。显然,我的路径上还有另一个64位的zlib1.dll副本,所以我的项目的64位版本可以正常工作。 - Bernard

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接