【问题标题】:strange level of indirection of a function call函数调用的奇怪间接级别
【发布时间】:2011-11-05 12:24:28
【问题描述】:

我正在编写一些低级代码,我注意到函数调用的一些不必要的间接级别,我根本不明白这种间接的原因是什么。这是揭示该行为的虚拟代码:

__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 字符缓冲区[123]; 返回 get_alignment(buf); 0041FA73 lea eax,[esp] 0041FA76 推eax 0041FA77 调用 get_alignment (40A38Fh) } ... 获取对齐: 0040A38F jmp get_alignment (41FA60h) ... __declspec(noinline) int get_alignment(void * ptr) { 返回 1; 0041FA60 移动 eax,1 }

所以,问题在于额外的间接级别: 获取对齐: 0040A38F jmp get_alignment (41FA60h)

WTF 是这样的吗?!我只是不明白,它不是从 dll 导入的函数,它是在可执行文件中定义的本地函数。该可执行文件经过各种优化(链接时间代码生成除外)编译。 如果我将static 添加到该get_alignment 的声明中,那么该额外的间接性就会消失。但我不是在寻找“修复”,我只是想了解为什么会有额外的跳跃!

在我的真实应用程序中,我实际上使用了一个用 .asm 文件编写的函数,但我只是不明白为什么会生成额外的跳转。似乎如果我在 C 模式(而不是 C++)中编译我的代码,那么我再也看不到那个级别的间接了......

任何人都可以对这种奇怪的行为有所了解吗?

谢谢!

【问题讨论】:

    标签: visual-studio-2008 visual-c++ x86


    【解决方案1】:

    这是链接器的 /INCREMENTAL 选项的副作用。这启用了增量链接和编辑+继续。当您在程序运行时编辑代码时使用跳转。替换函数被编译到另一个地址,并且 jmp 目标被修补以指向新函数。增量链接也使用它来避免从头开始重新创建二进制图像。

    【讨论】:

    • 我不使用 /ZI,我使用 /Zi。正如 Rayomond 指出的那样,问题在于增量链接。
    【解决方案2】:

    您可能启用了增量链接。增量链接模块“可能包含跳转 thunk 以处理将函数重定位到新地址。” http://msdn.microsoft.com/en-US/library/4khtbfyf(v=VS.80).aspx

    【讨论】:

    • 这对于增量链接或编辑+继续启用是有意义的,但在我的发布版本中,我不使用它们中的任何一个。似乎实际上启用了增量链接。 WTF,我将该设置保留为默认设置(未设置任何内容),VS默认启用它。我猜这是他们的错误,默认情况下不应该启用它。
    【解决方案3】:

    简而言之,在我的情况下,增量链接已启用,因为我没有为我的构建明确禁用它。 一般来说,链接器选项增量链接已被禁用以避免额外的跳转(/INCREMENTAL:NO 选项)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-01-27
      • 1970-01-01
      • 2012-07-17
      • 1970-01-01
      • 2016-04-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多