在不同编译器生成的代码之间传递结构

awe*_*kie 3 c struct

结构体的内存布局由编译器决定。那么,当一个编译器编译的某些代码使用由另一编译器编译的代码生成的结构时,会发生什么情况呢?

例如,假设我有一个声明 struct 的头文件somestruct和一个返回该结构的函数。一个源文件定义该函数并由编译器编译A。另一个源文件使用than函数并由编译器编译B并链接到另一个源文件的二进制文件。

如果两个编译器为 创建两种不同的布局somestruct,那么函数返回的变量的布局是什么?它是否遵循一个编译器的布局,或者当第二个源文件尝试访问第一个源文件返回的结构的元素时是否会出现内存错误?是编译时还是链接时出错?

Tim*_* Gu 5

该函数将返回由该函数编译器的 ABI 指定的结构。被调用者编译器只会将该函数视为符合其自身的 ABI 。

假设两个编译器使用相似的ABI,大多数情况下,在编译时或链接时甚至运行时都不会报告错误。对于某些兼容的编译器,例如 OS X 和 Linux 上的 Clang、GCC 和 Intel C 编译器,不应出现任何错误(如果出现错误,则表明是编译器的错误)。然而,在现实世界中,通常很难找到完全兼容的编译器(在大多数情况下,它们的 ABI 相似不完全相同;此类 ABI 错误将更难追踪,因为您的应用程序在某些非常奇怪的情况下会显得正常并崩溃)运行时遇到)。

正如 Basile 所说,C++ 的名称重整在 ABI 中带来了额外的差异,但这种差异在编译时更容易捕获,因为链接器实际上无法找到函数的符号,而不是找到不兼容的函数。

此外,传递结构是 ABI 方面的另一个令人头疼的问题,因为存在多种结构打包 ABI,有时甚至在 GCC/MinGW 和 MSVC 等“兼容”编译器中有所不同。(另请参阅-m[no-]ms-bitfieldsGCC 中的选项,该选项强制 GCC 对结构使用 MSVC ABI。)我还看到过一些情况,通过指针传递结构比通过值传递结构更可靠。