我正在从 C++ exe 中导出一个函数 [使用 _declspec(dllexport)]。当由 exe 本身调用时,该函数工作正常。我正在使用静态链接从另一个 exe [测试项目的 exe - 我将调用此 exe2] 加载此 exe(让我们称之为 exe1),即我在编译 exe2 时使用 exe1 的 .lib 文件,exe2 在启动时将其加载到内存中,就像任何dll。这会导致函数执行失败。
在函数内的 switch case 语句的反汇编中揭示了确切的问题。
exe1调用函数时的汇编代码
switch (dwType)
0040FF84 mov eax,dword ptr [dwType]
0040FF87 mov dword ptr [ebp-4],eax
0040FF8A cmp dword ptr [ebp-4],0Bh
0040FF8E ja $LN2+7 (40FFD2h)
0040FF90 mov ecx,dword ptr [ebp-4]
0040FF93 jmp dword ptr (40FFE0h)[ecx*4]
考虑最后两条指令。 mov 将传入的参数移动到 ecx 中。在 40EFF0h,我们有各个 case 语句的各种指令的地址。因此,jmp 会将我们带到相关的案例说明
exe2调用函数时的汇编代码
switch (dwType)
0037FF84 mov eax,dword ptr [dwType]
0037FF87 mov dword ptr [ebp-4],eax
0037FF8A cmp dword ptr [ebp-4],0Bh
0037FF8E ja $LN2+7 (37FFD2h)
0037FF90 mov ecx,dword ptr [ebp-4]
0037FF93 jmp dword ptr [ecx*4+40FFE0h]
发现哪里出了问题? 指令地址。代码现在已加载到内存中的不同位置。编译 exe1 时,编译器假定我们将始终启动它,因此它将始终在 0x0040000 处加载 [所有 Windows exe 都是如此]。因此它将一些值(如 40FFE0h)硬编码到指令中。仅在第二种情况下,40FFE0 与垃圾内存一样好,因为我们要查找的指令地址表不在此处。
如何在不将 exe1 转换为 dll 的情况下解决这个问题?
最佳答案
只是不要这样做。不值得这么麻烦。
我刚才试过做你正在尝试的事情。您可以通过更改“Linker->Advenced->Fixed base address”下属性窗口中的选项来解决不可重定位的 exe 问题,但随后您将遇到其他问题。
最终让我意识到这是浪费时间的事情是意识到 EXE 没有 DllMain()
函数。这意味着 CRT 库没有得到初始化,并且所有种类的东西都没有按照您期望的方式工作。
关于visual-c++ - 从 exe 加载 exe,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2048301/