【问题标题】:C++ and binary compatibility: returning a POD struct by valueC++ 和二进制兼容性:按值返回 POD 结构
【发布时间】:2011-06-08 16:26:21
【问题描述】:

考虑以下 C++ 代码:

struct X
{
        int a;
        int b;
};

X foobar()
{
        X x = { 1, 2 };
        return x;
}

现在假设这段代码被放在一个共享库中,供第三方应用程序使用。

我的问题是:如果我在X 的末尾添加另一个成员(例如int c),并在foobar() 中初始化它,调用foobar() 的现有应用程序会中断吗?请注意,这是关于二进制兼容性,而不是源代码兼容性。

【问题讨论】:

  • 如何使用“新”结构?客户端代码需要在标头中声明 X。你要申报哪个X?归根结底,您不想这样做,这就是发明 COM 之类的东西的原因。
  • X 在用于编译应用程序的标头中声明和定义。 foobar() 在标头中声明,但在共享库内的 .cpp 文件中定义。当然,如果X 更改,应用程序将不会重新编译,因此不会“看到”标头更改。因此问题。
  • 简短回答:不要这样做。长答案:你为什么要这样做?这里的真实情况是什么?
  • @Kerrek SB:在我的特殊情况下,这只是编写代码的最简单方法。还没有编写库和应用程序;我只是想知道如果X 发展,我是否可以写这个并且仍然保持二进制兼容性。好像不是这样,那我就换个方式写吧。不用担心。

标签: c++ binary-compatibility abi


【解决方案1】:

这完全取决于您的编译器选择做什么(更具体地说,是平台 ABI 规定的内容)。

您可以想象,如果将返回值放在堆栈上,那么您现在写入堆栈的内容会比调用者预期的要多,这可能会导致在某些东西上留下痕迹。

一般来说,您不应依赖任何特定的行为。您只需重新编译客户端应用程序。唯一现实的选择是PIMPL idiom

【讨论】:

  • 如何确定结果值是否入栈?
  • 不能,这是问题的一部分。
  • @e-t172:“确定”是什么意思? C++ 标准不涵盖这类事情,您正在查看纯粹的实现定义的结果。您将需要知道您的编译器如何安排堆栈(这将在编译器的 ABI 中定义)。一般来说,在这里依赖任何特定的行为都不是一个好主意。
  • 您可以合理地确定,无论 ABI 使用何种机制来返回类类型的对象,它都会在某些重要方面取决于它们的大小。 Oli 只是举了一个常见的例子——调用者为返回值提供了可用空间,因此如果大小不匹配,那么这个空间将被溢出。
【解决方案2】:

既然 X 的大小会改变,是的。数组等取决于大小。您可能会得到“幸运”,而填充可能会允许旧应用使用较新的库,但这纯粹是运气。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-11
    • 2010-11-24
    • 1970-01-01
    • 1970-01-01
    • 2020-05-12
    • 2011-08-03
    相关资源
    最近更新 更多