前言
最近项目里总是遇到 dll 加载不上的问题,原因各种各样。今天先总结一个虽然不是项目中实际遇到的问题,但是却非常经典的问题。其它几种问题,后续慢慢总结。
示例代码包含一个 exe 工程,两个 dll 工程。exe 会加载两个 dll 并调用它们的导出函数(GetCallCount),结果只有一个 dll 的导出函数被成功调用。会是什么原因呢?
现象
运行效果如下图:
通过 dumpbin 已经确认两个 dll 都有名为 GetCallCount 的函数。但是只有一个调用成功了,另外一个却调用失败。
使用 process explorer 观察 dll 加载情况,发现只加载了一个 dll,没发现另外一个 dll。
对于这个问题,如果我们使用 procmon 观察整个加载过程,看到的都是 Success。如下图:
说明,加载正常,在本地找到了这个文件,并正确的映射到内存空间中了。但为什么在进程中观察不到这个 dll 呢?是时候上调试器了。
上调试器
直接在 vs 中按 F5 启动,果然中断到 vs 中了。
从上图右侧部分,我们可以看到完整的调用栈。
这里简单介绍下相关代码。在 GlobalVariableInitializeOrder.cpp 的第 15 行调用了 HMODULE hDll2 = LoadLibraryA("GlobalVariableInitializeOrderDll2.dll"); 加载对应的模块。
Common\Test2.cpp 的第 10 行定义了全局变量 CTest2 g_t2;,问题就出在这个全局变量的初始化代码中。
从上图左侧部分,我们可以得知错误代码是 0xc0000005,内存访问异常。访问的地址是 0x00000004,对应的指令位置是 0x001EA6DB。
从上图中的反汇编看,确实是挂在了 001EA6DB mov eax,dword ptr [eax]。因为 eax 的值是 <

本文详细介绍了在调试过程中遇到的一个经典问题:DLL加载失败,原因是全局变量初始化异常。通过分析调用栈和全局变量初始化顺序,发现由于一个全局变量依赖另一个未初始化的全局变量导致崩溃。通过改变全局变量初始化顺序或消除依赖,问题得到解决。建议避免全局变量间的依赖,理解全局变量的初始化过程,并掌握调试技巧。
最低0.47元/天 解锁文章
2130

被折叠的 条评论
为什么被折叠?



