我正在使用 MinGW-Builds 在 64 位系统上编译 32 位 DLL 和 exe。 我正在使用
m32
位标志。 编译和链接阶段不会产生错误。 当我尝试运行该程序时,我得到:
应用程序无法正确启动(0xc000007b)。单击“确定”关闭应用程序。
我加载了 Dependency Walker,并收到以下错误消息:
错误:发现具有不同CPU类型的模块。
事实上,Dependency walker 显示我的 DLL 和可执行文件是 32 位的。 然而,它链接的其他所有内容都是 64 位的。 例如,NTDLL.DLL、MSVCRT.DLL、LIBWINPTHREAD-1.DLL 都标记为 64 位。 所以,我相信我没有正确链接 32 位 DLL。
让链接器链接 32 位 DLL 而不是 64 位 DLL 的命令是什么?
当我运行 32 位 Dependency Walker 配置文件模式时,我到底在寻找什么? 我在日志窗口中得到以下输出:
--------------------------------------------------------------------------------
Starting profile on 3/31/2014 at 10:14:41 PM
Operating System: Microsoft Windows NT/2000/XP/2003/Vista based Media Center (64-bit), version 6.01.7601 Service Pack 1
Program Executable: c:\mingw\msys\1.0\home\samuel\projects\bmd2\build\debug\32\testcore\BMD2TESTCORE.EXE
Program Arguments:
Starting Directory: C:\MinGW\msys\1.0\home\samuel\projects\bmd2\build\debug\32\testcore\
Search Path: C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;C:\MinGW\bin;C:\MinGW\libexec\gcc\x86_64-pc-mingw32\4.7.0;C:\Users\samuel\gcc\bin;C:\Users\samuel\gcc\libexec\gcc\x86_64-pc-mingw32\4.7.0;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files\Eclipse\adt-bundle\sdk\platform-tools;C:\Program Files\Eclipse\adt-bundle\sdk\tools;C:\Program Files (x86)\QuickTime\QTSystem\;C:\ant\bin;C:\Java\bin;C:\Program Files\TortoiseSVN\bin;C:\Users\samuel\Desktop\work\bmd2\build\debug\lib
Options Selected:
Simulate ShellExecute by inserting any App Paths directories into the PATH environment variable.
Log DllMain calls for process attach and process detach messages.
Log DllMain calls for all other messages, including thread attach and thread detach.
Hook the process to gather more detailed dependency information.
Log LoadLibrary function calls.
Log GetProcAddress function calls.
Log thread information.
Use simple thread numbers instead of actual thread IDs.
Log first chance exceptions.
Log debug output messages.
Log a time stamp with each line of log.
Automatically open and profile child processes.
--------------------------------------------------------------------------------
00:00:00.000: Started "BMD2TESTCORE.EXE" (process 0x1DC) at address 0x00400000 by thread 1. Successfully hooked module.
00:00:00.000: Loaded "NTDLL.DLL" at address 0x778C0000 by thread 1. Successfully hooked module.
00:00:00.031: Loaded "KERNEL32.DLL" at address 0x75510000 by thread 1. Successfully hooked module.
00:00:00.031: Loaded "KERNELBASE.DLL" at address 0x77340000 by thread 1. Successfully hooked module.
00:00:00.031: DllMain(0x77340000, DLL_PROCESS_ATTACH, 0x00000000) in "KERNELBASE.DLL" called by thread 1.
00:00:00.031: DllMain(0x77340000, DLL_PROCESS_ATTACH, 0x00000000) in "KERNELBASE.DLL" returned 1 (0x1) by thread 1.
00:00:00.031: DllMain(0x75510000, DLL_PROCESS_ATTACH, 0x00000000) in "KERNEL32.DLL" called by thread 1.
00:00:00.046: DllMain(0x75510000, DLL_PROCESS_ATTACH, 0x00000000) in "KERNEL32.DLL" returned 1 (0x1) by thread 1.
00:00:00.046: Injected "DEPENDS.DLL" at address 0x08370000 by thread 1.
00:00:00.078: DllMain(0x08370000, DLL_PROCESS_ATTACH, 0x00000000) in "DEPENDS.DLL" called by thread 1.
00:00:00.093: DllMain(0x08370000, DLL_PROCESS_ATTACH, 0x00000000) in "DEPENDS.DLL" returned 1 (0x1) by thread 1.
00:00:00.093: Loaded "MSVCRT.DLL" at address 0x75C90000 by thread 1. Successfully hooked module.
当您链接 DLL 时,您无需指定 DLL 的位数。您只需指定 DLL 的名称。由加载程序来查找具有您指定名称的 DLL。
您命名的两个 DLL(ntdll 和 msvcrt)是系统组件。它们驻留在 system32 目录中。您的 32 位进程受文件系统重定向器的约束。这意味着当加载程序在 system32 中查找时,重定向器会默默地将其映射到 syswow64(32 位系统目录)。这是透明地发生的,因此加载程序将找到 ntdll 和 msvcrt 的 32 位版本。
您报告的错误代码是
0xC000007B
。这是一个 NTSTATUS
错误代码。具体来说STATUS_INVALID_IMAGE_FORMAT
。这确实是当您尝试在 32 位进程中加载 64 位 DLL 时报告的错误。所以这很可能就是正在发生的事情。
您已经使用 Dependency Walker 完成了一些调试。这是完成这项工作的绝佳工具,但在您使用它的模式(静态模式)下,它有时会报告误报。听起来您正在使用 64 位版本的 Dependency Walker。使用 32 位版本您可能会获得更好的诊断效果。
综上所述,您真正需要做的就是在 Dependency Walker 的 Profile 模式下运行您的程序。这可以在“配置文件”菜单下找到。当您执行此操作时,您将从加载程序获得一串诊断信息,包括无法加载并出现错误
STATUS_INVALID_IMAGE_FORMAT
的 DLL 的名称。到那时就应该清楚出了什么问题。
您错误地使用了 Dependency Walker。
64 位版本的 Dependency Walker 不够智能,无法搜索 32 位 DLL 路径(David 的回答解释了程序运行时如何通过重定向实际使用这些路径)。
您需要使用 32 位 Dependency Walker 来分析 32 位代码。