在Visual Studio 2008(C ++)中调试一些代码,我注意到我的函数指针变量中的地址不是函数本身的实际地址。这是一个外部“C”函数。
int main() {
void (*printaddr)(const char *) = &print; // debug shows printaddr == 0x013C1429
}
Address: 0x013C4F10
void print() {
...
}
获取函数地址的反汇编是:
void (*printaddr)(const char *) = &print;
013C7465 C7 45 BC 29 14 3C 01 mov dword ptr [printaddr],offset print (13C1429h)
编辑:我在地址013C4F10查看了代码,编译器显然在该地址插入了“jmp”指令。
013C4F10 E9 C7 3F 00 00 jmp print (013C1429h)
实际上,.exe中的每个方法都有一个完整的跳转表。
有人可以解释为什么会这样做吗?它是一个调试“功能”吗?
答案 0 :(得分:19)
这是由“增量链接”引起的。如果在编译器/链接器设置中禁用它,则跳转将消失。
http://msdn.microsoft.com/en-us/library/4khtbfyf(VS.80).aspx
答案 1 :(得分:6)
我会冒这个猜测,但可能会启用Edit-and-Continue。
假设您需要重新编译该函数,您只需要更改间接表,而不是所有调用者。这将大大减少在执行“编辑并继续”功能时要执行的工作量。
答案 2 :(得分:2)
编译器在该地址处向实际方法插入“jmp”指令。
013C4F10 E9 C7 3F 00 00 jmp print (013C1429h)
实际上,.exe中的每个方法都有一个完整的跳转表。
这是一项调试功能。当我切换到释放模式时,跳转表消失,地址确实是实际的功能地址。