我有两个名为TestFunc和TestFunc2的空函数,我将它们的地址分配给两个变量。
void TestFunc()
{
}
__declspec(naked) void TestFunc2()
{
}
int main()
{
DWORD* test = (DWORD*)TestFunc;
DWORD* test2 = (DWORD*)TestFunc2;
printf("TestFunc is %p at test is %p\n", TestFunc, test);
printf("TestFunc2 is %p at test2 is %p\n", TestFunc2, test2);
getchar();
}
分配后,两个变量的值实际上与分配的值不同。
但是,在printf语句中,输出显示它们是相同的。任何想法为什么会发生这种情况?
答案 0 :(得分:7)
这是由Visual Studio中的incremental linking引起的,从此页面可以了解到其中一个缺点是:
增量链接程序在功能上等同于非增量链接的程序。但是,因为它是为后续增量链接,增量链接的可执行文件,静态库或动态链接库文件而准备的:
- 由于代码和数据的填充,大于非增量链接的程序。填充使链接器可以增加函数和数据的大小,而无需重新创建文件。
- 可能包含跳转thunk以处理将函数重定位到新地址。
那些 跳跃 就是您所观察到的。
如果禁用此选项(vs2015):
链接器 - >所有选项 - >启用增量链接到NO
然后你的地址将是平等的。
如果您仔细观察反汇编在您分配给DWORD *的地址的位置,您会发现跳转到您的函数:
TestFunc:
000000014001117C jmp TestFunc (01400116D0h)
答案 1 :(得分:1)
它与您编写代码的特定于平台的运行时环境有关。 C ++允许运行时在场景后面做一些指针算术。编写依赖于此运行时行为的任何代码是危险的。
如果您真的想知道,请查看内存中的汇编程序代码。我的猜测是运行时使用额外的跳转表可能用于新的编辑,并继续调试功能,每个版本的visual studio都会改进/更改。