關於debug編譯下函數名字地址和函數中實際打印出來的地址不一致的問題

自定義了一個函數

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模式下屬性頁-連接器-啓用增量鏈接選擇否。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章