C ABI:正在改变一个void函数来返回int一个突破性的变化?

时间:2013-03-25 23:13:20

标签: c return-type abi

是否有任何非奇特的架构/ OS /编译器改变:

void func(void *, int, int)

为:

int func(void *, int, int)

会打破ABI吗? (即,使用“int”版本运行时,为“void”版本的共享库编译的程序会中断)

1 个答案:

答案 0 :(得分:8)

有几条评论说没有,我们可以通过一点推理加强这一点。在最熟悉的ABI中,允许使用带有声明void func(void *, int, int)的函数来使用寄存器,其中int结果将作为临时寄存器返回;它不需要保存和恢复它。声明为int func(void *, int, int)的函数必需,以使用将返回int结果的寄存器。在其他方面,这些声明是相同的。因此,int func(void *, int, int)的任何实现的机器代码也是满足void func(void *, int, int)的机器代码。

换句话说,调用者无法区分故意在返回寄存器中返回结果的机器代码,这些代码恰好会在该寄存器中留下一些临时计算。

请注意,这种推理要求被调用函数隐藏在ABI后面;它依赖于ABI指定的二进制行为。如果在编译被调用函数时(或者可能影响调用实现方式的实现的其他部分)可以看到被调用函数的源,那么优化可能导致绕过ABI的行为(例如,观察被调用的例程)不使用返回寄存器,因此在调用者中使用它来保持一些预期在调用中保持不变的值。)

由于您说这是针对共享库的,因此您可能很安全:共享库是单独编译的,其源不可供其调用者使用。但是,您应该考虑辅助渠道。例如,共享库可能是共享源并包含跨库调用的一组库的一部分。在这种情况下,某人可能拥有旧版本的共享库,该库使用void源的视图和包含int源的共享库的新版本进行编译。 (甚至这需要不寻常的源代码安排或花哨的编译器,它们将信息集成到多个编译单元中。)