我在看这个:Importing Function Calls Using __declspec(dllimport)我不明白为什么真的需要 __declspec(dllimport)?为什么链接器不能在链接阶段将调用 func1 修补为调用 DWORD PTR __imp_func1(IAT 表地址),从而避免在源代码中单独声明?
问问题
295 次
2 回答
2
修补指令的空间不足可能是一个原因,但不是主要原因。即使有足够的空间,链接器仍然不会修补它以获得更好的性能。原因是链接器不执行或修改编译器后端生成的代码,它只是用重定位信息修补位置。下面的例子不是很好的编码风格,但清楚地解释了这个问题。生成的指令bar()
是call dword[_imp__bar]
6 个字节长,即使链接器知道bar()
最终图像中定义的知识,它也不会对其进行修补call OffsetOfBar
,只需要 5 个字节。将代码生成延迟到链接时间(将/GL传递给cl.exe)可以解决这个问题,因为链接器会在链接时间调用编译器后端,后端会生成优化的call
指令,因为它知道call
目标在同一个模块中。
// main.c
// compile it with 'cl.exe /Zi /O2 main.c bar.c'
__declspec(dllimport) void bar();
int main() {
bar();
}
// bar.c
void __declspec(noinline) bar() {}
于 2014-01-22T06:28:56.530 回答
1
引用 Raymond Chen: call func 的长度为 5 个字节,但 call dword ptr [_ imp _func] 的长度为 6 个字节。补丁不适合。一个字节太大了。在每条调用指令之后添加一个 nop(以防它碰巧被导入)听起来非常过分。
于 2013-04-04T13:46:24.550 回答