函数指针的对齐要求

Alignment requirement of function pointers

本文关键字:对齐 指针 函数      更新时间:2023-10-16

我们知道指向数据的指针的值应该正确对齐。例如,指向double的指针的值应该是 8 的倍数。所以我想知道指向函数的指针是否有类似的要求。

数据和代码的对齐高度依赖于机器。

在许多处理器上,例如在未对齐的地址上读取double会导致故障(硬件异常、陷阱或任何你想称呼它的东西)——这要么在软件中处理[速度慢,通常比对齐访问慢 10-1000 倍],要么导致执行操作的应用程序失败(类似于访问现代操作系统中的无效内存位置)。例如,在x86上,它会更慢,但通常不会失败,因为至少在某些情况下,处理器必须执行两个较小的读取操作并组合这些操作才能获得double的值。

代码也可能具有对齐方式。大多数RISC处理器都有固定大小的代码字 - 4字节是通信大小,它们应该与该大小对齐。"拇指"模式下的 ARM 使用 2 字节指令大小,一些指令在后面的另一个单词中具有额外的数据。

另一方面,x86 具有"单字节"对齐要求,例如 68K 要求代码仅以 2 个字节对齐。因此,在这方面,对齐需求会有所不同。除此之外,有一定的对齐效率原因 - 例如在 8、16 或 32 字节边界处启动函数/分支通常是有益的,我知道一些较旧的 x86 处理器对"给定 N 字节代码可能有多少分支预测"有限制——这意味着如果你在一小段代码中有许多不同的分支, 有些人将不得不在没有分支预测的情况下进行,因为该位置的"插槽"已经满了。

因此,出于性能原因,编译器(有时)会填充代码以对齐函数。然而,这并不总是一个胜利 - 它浪费了"填充"的缓存空间,这实际上取决于代码的使用方式。编译器通常知道这一点,至少如果您使用基于反馈/配置文件的优化(其中代码与检测一起运行以计算代码的使用方式,并且优化基于此结果)。

但是,通常,函数指针可以指向任何作为"代码"合法地址的地方,因此基本要求通常是 1、2 或 4 个字节,具体取决于处理器本身的体系结构。