我正在写一些低级代码,我注意到函数调用的一些不必要的间接性,我根本就没有得到这个间接的原因。这是显示该行为的虚拟代码:
__declspec(noinline) int get_alignment(void * ptr)
{
return 1;
}
__declspec(noinline) int test123()
{
char buf[123];
return get_alignment(buf);
}
然后,当我在asm模式(Ctrl + F11)的调试器中逐步执行函数test()内的代码时,我看到了:
__declspec(noinline) int test123() { 0041FA70 sub esp,7Ch char buf[123]; return get_alignment(buf); 0041FA73 lea eax,[esp] 0041FA76 push eax 0041FA77 call get_alignment (40A38Fh) } ... get_alignment: 0040A38F jmp get_alignment (41FA60h) ... __declspec(noinline) int get_alignment(void * ptr) { return 1; 0041FA60 mov eax,1 }
所以,问题是关于额外的间接水平: get_alignment: 0040A38F jmp get_alignment(41FA60h)
WTF是关于什么的?!我只是没有得到它,它不是来自dll的导入函数,它是可执行文件中定义的本地函数。此可执行文件使用各种优化(链接时间代码生成除外)编译。
如果我将static
添加到get_alignment的声明中,那么额外的间接消失了。但我不是在寻找一个“修复”,我只想了解为什么那里会有额外的跳跃!
在我的真实应用程序中,我实际上使用了.asm文件中编写的函数,我只是不明白为什么会产生额外的跳转。似乎如果我在C模式(而不是C ++)中编译我的代码,那么我再也看不到间接级别......
任何人都可以对这种奇怪的行为有所了解吗?
谢谢!
答案 0 :(得分:2)
您可能已启用增量链接。增量链接模块“可以包含跳转thunk以处理将函数重定位到新地址”。 http://msdn.microsoft.com/en-US/library/4khtbfyf(v=VS.80).aspx
答案 1 :(得分:2)
这是链接器的/ INCREMENTAL选项的副作用。这将启用增量链接和编辑+继续。在程序运行时编辑代码时使用跳转。替换函数被编译到另一个地址,并且jmp目标被修补以指向新函数。增量链接也使用它,以避免必须从头开始重新创建二进制图像。
答案 2 :(得分:1)
简而言之,在我的情况下,启用了增量链接,因为我没有为我的构建明确禁用它。 通常,链接器选项可以禁用增量链接以避免额外跳转(/ INCREMENTAL:NO选项)