首页 > 解决方案 > C语言中的加载库

问题描述

我有一个使用 LCC 编译器在 Matlab 中生成的 DLL,我想从这个 DLL 中调用一个函数。DLL的名称是fcn_acDklGenerator,函数的名称也是fcn_acDklGenerator,所以我写了下面的代码,但是加载库失败。

char* libName = "\\fcn_acDklGenerator.dll";
TCHAR libFullPath[MAX_PATH + 1] = { 0 };
GetCurrentDirectory(MAX_PATH, libFullPath);
strcat_s(libFullPath, sizeof libFullPath, libName);
HMODULE matlab = LoadLibrary(libFullPath);

LoadLibrary 的输出为 NULL,而我检查了 libFullPath 值,并且我确信 DLL 位于该路径。

标签: cloadlibrary

解决方案


可能有很多原因和许多技术可以追踪它们,所以这里有一个社区 Wiki 答案,希望可以帮助许多面临 DLL 加载问题的人:

LoadLibrary 可能失败的原因:

  • .dll 文件未找到、不可读或不可执行。(这可能会因不同的搜索路径规则、文件系统重定向、已加载到进程中的另一个同名 DLL、SxS 缓存、ACL、独占共享、被标记为删除、恶意软件保护工具的干扰等而变得复杂。)

  • DLL 是 64 位的,而您正试图将其加载到 32 位进程中,反之亦然。

  • DLL 依赖(直接或间接)另一个加载失败的 DLL。(换句话说,这个列表可能需要递归应用。)

  • DLL 没有可用的合理地址范围(极不可能)。

  • DllMain(或其他名称的等效函数)使用错误的调用约定。

  • DLLMain 返回错误。

  • DllMain 创建一个死锁。虽然这通常会导致挂起,但可以想象,在某些情况下,加载程序可能会检测到它并导致加载失败。

诊断特定实例的技术:

  • 在调用 LoadLibrary 失败后立即检查GetLastError通常有助于缩小可能性。

  • 根据进程的SetErrorMode设置,您还可以从出现的对话框中收集一些信息。

  • 在调试器(如 Visual Studio)中跳过 LoadLibrary 调用可以在调试输出窗口中给出提示,因为您可能会看到哪些其他 DLL 与您请求的 DLL 一起加载。

  • 您还可以使用诸如 Sysinternals 的 PROCMON 之类的工具来查看实际搜索了哪些路径、打开文件失败的 I/O 错误类型等。

  • 您可以暂时将复杂的 DllMain 替换为普通的 DllMain,以确定复杂的 DllMain 是否导致故障。

dumpbin 和 DependencyWalker 等工具可以回答有关位数、是否导出 DllMain 以及需要哪些其他 DLL 的问题。


推荐阅读