2013-04-04 58 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() {}