c - 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 位于该路径。
解决方案
可能有很多原因和许多技术可以追踪它们,所以这里有一个社区 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 的问题。
推荐阅读
- angular - 如何通过角度获取函数中输入字段的值?
- azure - 在 .NetCore 中实现 Key Vault 并将值转换为 Startup.cs .NetCore 应用程序中的模型
- sql - 无代理键的 SCD 1 维
- javascript - 使用 prinThis.js 打印我的模式后,我的 CSS 消失了
- android - 片段中未显示日期选择器对话框
- php - 数据库查询构建器使用关系
- python - 只读全局变量是可接受的做法吗?
- android-studio - 可以在没有点的情况下显示颤振项目的实际文件夹结构
- javascript - 如何从单选按钮获得不同的值?
- python - 如何使用 plotly 向 mapbox 添加多个图层?