我在使用LoadLibrary()时出现问题并收到一条对我没有意义的错误:
::SetLastError(0);
m_hDll = ::LoadLibrary(szName);
if (m_hDll == NULL) // Failure to load the DLL.
{
DWORD err = GetLastError();
}
错误是127(“无法找到指定的过程。”)在调用LoadLibrary()时对我没有任何意义。我没有调用GetProcaddress( )。
DLL(和应用程序)都是用VS ++ 2005 SP1编译的。
可能出现什么问题?
答案 0 :(得分:25)
让我们一步一步:
错误消息表示找到了dll但缺少必需的功能。 (抖动是对的。)这意味着你有你需要的DLL,但不是正确的版本。 (Davefiddes是对的,虽然问题可以是任何dll,而不仅仅是Microsoft运行时库。而且,至少对于主要更新,Microsoft为其运行时库提供了不同的名称,因此在这种情况下它不会成为问题。)< / p>
这没有意义,因为没有从被加载的DLL请求任何功能。 (亚当是对的。)
因此,预计缺少的函数不会出现在LoadLibrary命令显式加载的dll中,而是出现在同时隐式加载的依赖dll中,因为第一个dll需要它。 (Zebrabox很接近。)
从属dll是一个dll,它通过导入库或.lib文件“”静态“链接到显式加载的库,包含在显式加载的dll的链接器步骤中。 (我打赌你不知道“动态链接库”可能是“静态链接的。”嗯,现在你做了。)
如果您在不同的文件夹中有相同dll的多个版本,那么这也可能是搜索路径问题(正如zebrabox建议的那样)。 Dll路径搜索顺序本身就是一个复杂的主题:见http://msdn.microsoft.com/en-us/library/ms682586(VS.85).aspx。这取决于操作系统等。在可行的情况下,最安全的做法是将所有潜在的问题dll放在与exe相同的文件夹中。
依赖dll也可以有自己的依赖dll,这可能会使这个问题很难解决。取决于可能会有所帮助,但如果没有,请尝试filemon。在您的错误消息之前成功读取的最后一个dll是错误的版本。
答案 1 :(得分:6)
Microsoft gflags工具将始终告诉您哪些依赖项无法加载以及原因。
运行gflags -i your_application.exe +sls
。之后,在调试器下执行应用程序以捕获loader traces。
gflags是Debugging Tools的一部分 - 您可以查看C:\Program Files (x86)\Windows Kits\10\Debuggers\x64
以查看您是否已拥有它。您可以将该目录添加到路径中,或者只在cmd.exe中从该目录执行gflags。
例如,在运行gflags之后,在::LoadLibrary(_T("foo"))
调用上放置一个断点并在Visual Studio输出窗口中查找加载程序错误时跳过它,例如。
4b00:396c @ 479194074 - LdrpSnapThunk - ERROR: Procedure "?SetObject@vis_DollarMap@@QEAAXHPEAX@Z" could not be located in DLL "bar.dll"
First-chance exception at 0x0000000077307EF8 (ntdll.dll) in your_application.exe: 0xC0000139: Entry Point Not Found.
4b00:396c @ 479194074 - LdrpGenericExceptionFilter - ERROR: Function LdrpSnapIAT raised exception 0xc0000139
Exception record: .exr 0000000000129070
Context record: .cxr 0000000000128B80
4b00:396c @ 479194074 - LdrpHandleOneOldFormatImportDescriptor - ERROR: Snapping the imports from DLL "C:\test\64Debug\foo.DLL" to DLL "C:\test\64Debug\bar.dll" failed with status 0xc0000139
这意味着在加载foo.dll
期间,导入了依赖项bar.dll
,导致bar.dll
导入失败。
依赖项导入失败,因为缺少过程?SetObject@vis_DollarMap@@QEAAXHPEAX@Z
- 您可以demangle到public: void __cdecl vis_DollarMap::SetObject(int,void * __ptr64) __ptr64
。
您可能拥有错误的依赖版本 - 也许您需要重建依赖项以使其更新。
之后运行gflags -i your_application.exe -sls
以禁用加载程序跟踪。
答案 2 :(得分:4)
错误消息表示找到了适当的DLL但缺少必需的过程导出。你有正确版本的DLL吗?
您可以使用dumpbin.exe
检查DLL导出的功能并检查拼写。
答案 3 :(得分:4)
安装调试工具并运行gflags -i your_application.exe +sls
。之后,在调试器下执行应用程序以捕获加载程序跟踪。
答案 4 :(得分:2)
您的应用程序运行时与DLL之间是否存在不匹配?
过去在VS 2005中遇到的一个问题是,一部分是作为Release构建而另一部分构建为Debug构建。这些不同版本的Microsoft运行时DLL是不兼容的,因为在给定的进程中只能加载一个。
我认为你看错误127的原因是因为你的DLL在加载的运行时DLL中寻找一个不存在的函数,因为它是错误的运行时。
答案 5 :(得分:1)
我的两个猜测
1. LoadLibrary调用指定DLL的DllMain(第一次尝试并附加到您的进程)。远射,但它在那里?
2. LoadLibrary将加载指定的DLL及其所有依赖项。因此,如果DLL的依赖模块不能位于将导致加载失败的搜索路径中 - 您可以使用depends.exe进行检查 - 可用here
答案 6 :(得分:0)
调用LoadLibrary()后,我得到了相同的错误代码。最后通过依赖walker找到了模块(szName)的某些依赖项缺失。
答案 7 :(得分:0)
我建议使用Dependency Walker找出缺少哪种方法或者需要或缺少哪些DLL。
答案 8 :(得分:0)
好的,这是我的解决方案:我们有一个复杂的依赖系统,其中有两个DLL,它们的名称相同,即相同(即server.dll
),但它们位于不同的路径上。
当client.dll
加载了LOAD_WITH_ALTERED_SEARCH_PATH
时,看来Windows无法确定符号解析中应使用server.dll
中的哪一个(两者{{1} }已成功加载)。
解决方案非常简单:让加载的dll具有唯一的名称,即server.dll
和server-1.dll
。