在类中添加枚举定义会破坏其二进制向后兼容性吗?

发布于 2024-12-16 19:02:19 字数 894 浏览 1 评论 0原文

我知道添加 static 成员函数很好,但是 enum 定义怎么样?没有新的数据成员,只有它的定义。


一点背景知识:

我需要添加一个 static 成员函数(在类中),它将通过其字符串表示形式识别(该函数)IP 地址的版本。我想到的第一件事是为 IPv4IPv6Unknown 声明一个 enum 并进行我的函数的这个 enum 返回代码。

但我不想破坏二进制向后兼容性。

这是一个非常糟糕的问题(对于SO) - 这里有任何来源或问题吗,我可以阅读更多相关内容?我的意思是-什么破坏了二进制兼容性,什么-则不会。或者它取决于很多东西(比如架构、操作系统、编译器......)?


编辑:关于 @PeteKirkham 的评论:好吧,至少 - 有没有办法测试/检查更改 ABI 或者最好发布有关该问题的新问题?

EDIT2:我刚刚发现了SO问题:检测 C++ 中 ABI 中断的静态分析工具 。我认为它在某种程度上与这里相关,并回答了有关检查二进制兼容性的工具的部分。这就是为什么我在这里将其联系起来。

I know adding static member function is fine, but how about an enum definition? No new data members, just it's definition.


A little background:

I need to add a static member function (in a class), that will recognize (the function) the version of an IP address by its string representation. The first thing, that comes to my mind is to declare a enum for IPv4, IPv6 and Unknown and make this enum return code of my function.

But I don't want to break the binary backward compatibility.

And a really bad question (for SO) - is there any source or question here, I can read more about that? I mean - what breaks the binary compatibility and what - does not. Or it depends on many things (like architecture, OS, compiler..)?


EDIT: Regarding the @PeteKirkham 's comment: Okay then, at least - is there a way to test/check for changed ABI or it's better to post new question about that?

EDIT2: I just found a SO Question : Static analysis tool to detect ABI breaks in C++ . I think it's somehow related here and answers the part about tool to check binary compatibility. That's why I relate it here.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

花之痕靓丽 2024-12-23 19:02:19

这里真正的问题显然是为什么使其成为类(静态)成员?

从定义中可以明显看出,这完全可以是其自己的命名空间(可能还有头文件)中的自由函数,或者如果使用是在源文件内的匿名命名空间中隔离定义的。

尽管这仍然可能破坏 ABI,但确实需要一个有趣的编译器才能做到这一点。

至于 ABI 破坏:

  • 修改类的大小:添加数据成员,除非您设法将它们存储到以前未使用的填充中(当然是编译器特定的)
  • 修改类的对齐方式:更改数据成员,有一些技巧可以人为地膨胀对齐(联合)但缩小它需要编译器特定的编译指示或属性以及
  • 修改 vtable 布局的兼容硬件:添加虚拟方法可能会更改 vtable 中先前虚拟方法的偏移量。对于 gcc,vtable 是按照声明的顺序布局的,因此在末尾添加虚拟方法是可行的...但是它在基类中不起作用,因为 vtable 布局可能与派生类共享。 最好考虑冻结
  • 修改函数的签名:符号的名称通常取决于函数本身的名称及其参数的类型(加上方法的类名称和限定符)的方法)。您可以在参数上添加顶级 const,无论如何它都会被忽略,并且您通常可以更改返回类型(但这可能会带来其他问题)。请注意,添加具有默认值的参数确实会破坏ABI,就签名而言,默认值将被忽略。 最好考虑冻结
  • 删除以前导出符号的任何函数或类(即具有直接或继承虚拟方法的类)

我可能已经忘记了一两点,但这应该已经让您继续前进一段时间了。

ABI 的示例:Itanium ABI

The real question here, is obviously WHY make it a class (static) member ?

It seems obvious from the definition that this could perfectly be a free function in its own namespace (and probably header file) or if the use is isolated define in an anonymous namespace within the source file.

Although this could still potentially break ABI, it would really take a funny compiler to do so.

As for ABI breakage:

  • modifying the size of a class: adding data members, unless you manage to stash them into previously unused padding (compiler specific, of course)
  • modifying the alignment of a class: changing data members, there are tricks to artificially inflate the alignment (union) but deflating it requires compiler specific pragmas or attributes and compliant hardware
  • modifying the layout of a vtable: adding a virtual method may change the offsets of previous virtual methods in the vtable. For gcc, the vtable is layed out in the order of declaration, so adding the virtual method at the end works... however it does not work in base classes as vtable layout may be shared with derived classes. Best considered frozen
  • modyfing the signature of a function: the name of the symbol usually depends both on the name of the function itself and the types of its arguments (plus for methods the name of the class and the qualifiers of the method). You can add a top-level const on an argument, it's ignored anyway, and you can normally change the return type (this might entails other problems though). Note that adding a parameter with a default value does break the ABI, defaults are ignored as far as signatures are concerned. Best considered frozen
  • removing any function or class that previously exported symbols (ie, classes with direct or inherited virtual methods)

I may have forgotten one or two points, but that should get you going for a while already.

Example of what an ABI is: the Itanium ABI.

¢好甜 2024-12-23 19:02:19

正式...如果您链接针对两个不同的文件编译的文件
您的类的版本,您违反了单一定义规则,该规则
是未定义的行为。实际上...关于唯一会损坏的东西
二进制兼容性正在添加数据成员或虚拟函数
(非虚函数都可以),或者更改一个函数的名称或签名
函数,或任何涉及基类的东西。这似乎是
通用——我不知道哪个编译器的规则在哪里
不同的。

Formally... If you link files which were compiled against two different
versions of your class, you've violated the one definition rule, which
is undefined behavior. Practically... about the only things which break
binary compatibilty are adding data members or virtual functions
(non-virtual functions are fine), or changing the name or signature of a
function, or anything involving base classes. And this seems to be
universal—I don't know of a compiler where the rules are
different.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文