缘起
最近,项目里遇到一个 dll
加载不上的问题。实际项目比较复杂,但是解决后,又是这么的简单,合情合理。本文是我使用示例工程模拟的,实际项目中另有玄机,但问题的本质是一样的。本文从行文上与 《调试实战 —— dll 加载失败之全局变量初始化篇》 非常相似,示例代码也非常相似(原谅我比较懒),感兴趣的小伙伴儿可以对比来读。
背景介绍
示例代码中一共有四个工程,一个 exe
,三个 dll
。其中,Base.vcxproj
是封装了公共接口的工程,会生成 Base.dll
。Extension1.vcxproj
和 Extension2.vcxproj
非常相似,会分别生成 Extension1.dll
和 Extension2.dll
。MixConfiguration.vcxproj
会生成 MixConfiguration.exe
,该 exe
会加载 Extension1.dll
和 Extension2.dll
,并调用它们的导出函数(象征性的调用)。程序运行起来后,发现只有一个 dll
的功能正常,另外一个 dll
的功能执行不正常。如下图:

已经使用 dumpbin
确认两个 dll
都有名为 GetCallCount
的函数。但是只有一个调用成功了,另外一个却调用失败。

使用 process explorer
观察 dll
加载情况,发现只加载了一个 dll
,没发现另外一个 dll
。

与上一个问题一样,如果我们用 procmon
观察整个加载过程,看到的都是 Success
。这里不截图了。直接上调试器。
上调试器
直接在 vs
中按 F5
启动,果然中断到 vs
中了。

从上图右侧部分,可以看到完整的调用栈。
简单介绍下相关代码。在 MixConfiguration\Entry.cpp
的第 15
行调用了auto hDll2 = LoadLibraryA("Extension2.dll");
加载对应的模块。在 Extension2\Extension2.cpp
的第 22
行定义了全局变量 CTest2 g_t2
,问题就出在这个全局变量的初始化代码中。
从上图左侧部分可知,错误代码是 0xc0000005
,内存访问异常。访问的地址是 0x0000000D
,对应的指令地址是 008B7F34
。

从上图可以看出,确实是挂在了 008B7F34 movsx ecx,byte ptr [