Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Will adding enum definition inside a class break its binary-backward-compatibility?

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.

like image 901
Kiril Kirov Avatar asked Nov 18 '11 14:11

Kiril Kirov


2 Answers

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.

like image 59
Matthieu M. Avatar answered Oct 19 '22 03:10

Matthieu M.


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.

like image 31
James Kanze Avatar answered Oct 19 '22 03:10

James Kanze