自定義了一個函數
void Func(){
FARPROC C = Func;
printf("%08x\n", C); // 這裏C的地址和B的地址一致,函數的實際地址; 查找函數地址之間的偏移,要找這個地址;
}
然後:DWORD dwStart=(DWORD)Func; // 對應於IAT裏面的函數地址; 和函數實際地址不一致;
調試監視 dwStart與Func兩值不同
拿到OD裏看了下發現是這樣的
0062D7D3 . /E9 68050100 JMP demo.0063DD40
原來debug版本的地址都是
A:jmp B
B:Func()。
dwStart得到的地址是A,Func得到的是B
所以會不一樣。
因爲VC中會生成一個函數的符號以及函數實際地址對應的表,當調用1個函數時,先得到的是函數的符號地址,而這些符號地址裏面都是對應1個跳轉指令,指向函數的實際地址。如果去掉程序的incremental link選項,就是跳到直接的函數地址,而沒有中間的jmp了。
Link incrementally允許連結函式時多留一些額外的空間。這個空間只是函數式之間的餘隙,並不影響程序的運行,但會使程序體積變大不少。這樣做的好處是:當連結完成後,連結器會把函數式連結的相關信息儲存到數據庫。當程序員修改某個函式,只要該函式增加的程序不超過保留的額外的空間,當程序再編譯連結時便不需要對其它的函式重新relocate address,這樣會使連結的速度加快很多。這用在更改程序頻繁的debug時期當然是很好的功能,但當程序 release時就不需要這些多餘的空間了。所以一般會在debug mode 時enable Link incrementally,release時則disable它。簡單的說增量鏈接是編譯器爲了減少鏈接時間做的處理,把函數體用一個JMP指令代替,這樣就可以隨意改變函數的內容,而不用修改CALL指令。
要關閉就在debug模式下屬性頁-連接器-啓用增量鏈接選擇否。