简体   繁体   English

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

[英]C ABI: is changing a void function to return an int a breaking change?

Is there any non-exotic architecture/OS/compiler where the change of: 是否有任何非奇特的架构/ OS /编译器的变化:

void func(void *, int, int)

to: 至:

int func(void *, int, int)

would break the ABI? 打破ABI? (ie a program compiled for "void" version of a shared library would break when run with the "int" version) (即,使用“int”版本运行时,为“void”版本的共享库编译的程序会中断)

Several comments have said no, and we can strengthen that with a little reasoning. 有几条评论说没有,我们可以通过一点推理加强这一点。 In the most familiar ABIs, a function with declaration void func(void *, int, int) is permitted to use the register in which an int result would be returned as a scratch register; 在最熟悉的ABI中,允许使用声明void func(void *, int, int)函数来使用寄存器,其中int结果将作为临时寄存器返回; it need not save and restore it. 它不需要保存和恢复它。 A function with declaration int func(void *, int, int) is required to use the register in which an int result would be returned. 声明为int func(void *, int, int)函数需要使用将返回int结果的寄存器。 In other respects, these declarations are identical. 在其他方面,这些声明是相同的。 Therefore, the machine code of any implementation of an int func(void *, int, int) is also machine code that satisfies void func(void *, int, int) . 因此, int func(void *, int, int)的任何实现的机器代码也是满足void func(void *, int, int)机器代码。

Put another way, the caller has no way of distinguishing machine code that deliberately returns a result in the return register from code that happens to leave some scratch calculation in that register. 换句话说,调用者无法区分故意在返回寄存器中返回结果的机器代码,该代码恰好在该寄存器中留下了一些临时计算。

Note that this reasoning requires that the called function be hidden behind an ABI; 注意,这种推理要求被调用的函数隐藏在ABI后面; it relies on the binary behavior specified by the ABI. 它依赖于ABI指定的二进制行为。 If the source of the called function is visible when the called function is compiled (or other parts of the implementation that might affect how the call is implemented), then optimization could result in behaviors that bypass the ABI (eg, observing that the called routine does not use the return register and therefore using it in the caller to hold some value expected to remain unchanged over the call). 如果在编译被调用函数时(或者可能影响调用实现方式的实现的其他部分)可以看到被调用函数的源,那么优化可能导致绕过ABI的行为(例如,观察被调用的例程)不使用返回寄存器,因此在调用者中使用它来保持一些预期在调用期间保持不变的值)。

Since you say this is for a shared library, you are likely safe: The shared library is compiled separately, and its source is not available to its callers. 由于您说这是针对共享库的,因此您可能很安全:共享库是单独编译的,其源不可用于其调用者。 However, you should consider side channels. 但是,您应该考虑辅助渠道。 For example, perhaps the shared library is part of a set of libraries that share sources and contain cross-library calls. 例如,共享库可能是共享源并包含跨库调用的一组库的一部分。 In this case, somebody might have an old version of a shared library that was compiled with a view to the void source and a new version of the shared library that contains the int source. 在这种情况下,某人可能有一个旧版本的共享库,该库是使用void源视图和包含int源的共享库的新版本编译的。 (And even this requires unusual source code arrangements or fancy compilers that integrate information across multiple compilation units.) (甚至这需要不寻常的源代码安排或花哨的编译器,它们将信息集成到多个编译单元中。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM