2013-04-04 62 views
3

我在看:Importing Function Calls Using __declspec(dllimport),我不明白为什么__declspec(dllimport)真的需要?为什么链接器补丁在链接阶段无法调用func1调用DWORD PTR __imp_func1(IAT表地址),从而避免需要在源中单独声明?__declspec(dllimport)的必要性

+0

这将有助于:http://stackoverflow.com/a/4490536/? – Joulukuusi 2013-04-04 13:15:17

+0

@Joulukuusi是的,这是一个优化,以避免jmp,但我不明白为什么这种优化不能由链接器执行。 – user206334 2013-04-04 13:17:44

+4

由于'call func'长度为5个字节,但'call dword ptr [__imp__func]'长度为6个字节。该补丁不适合。这是一个太大的字节。 – 2013-04-04 13:21:41

回答

1

引用Raymond Chen:call func长度为5个字节,但调用dword ptr [_ imp _func]长度为6个字节。该补丁不适合。这是一个太大的字节。在每个调用指令之后添加一个nop(以防万一它被导入)听起来非常过分。

2

补贴说明的空间不大可能是一个原因,但不是主要原因。即使有足够的空间,链接器仍然不会打补丁,以获得更好的性能。原因是链接器不会执行或修改由编译器后端生成的代码,它只是用重定位信息来修补这些地方。下面的例子不是很好的编码风格,而是清楚地解释问题。对于bar()生成的指令是call dword[_imp__bar],它是6个字节长,即使链接器知道bar()是在最终映像中定义的,但它不会用仅需要5个字节的call OffsetOfBar进行修补。将代码gen延迟到链接时间(pass/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() {}