ALLCODE CRAFT

20 ABI (Application Binary Interface) breaking changes every C++ developer should know

What is an Application Binary Interface ?

According to Wikipedia, " an application binary interface (ABI) is an interface between two binary program modules; often, one of these modules is a library or operating system facility, and the other is a program that is being run by a user.

An ABI defines how data structures or computational routines are accessed in machine code, which is a low-level, hardware-dependent format; in contrast, an API defines this access in source code, which is a relatively high-level, hardware-independent, often human-readable format. A common aspect of an ABI is the calling convention, which determines how data is provided as input to or read as output from computational routines; examples are the x86 calling conventions."

Why should I care about ABI Compatibility?

If you're packaging your library as a dynamic library(dll), you should be careful not to break ABI compatibility. If ABI compatibility is broken between the calling binary (exe or another dll) and your dll, it can result in unintended crashes.

  • ABI Breaking Changes
  • ABI COMPATIBLE CHANGES

1. Un-export or remove a class from the dll

2. Un-export or remove a function or method from a class

3. Change the signature of any method in the class. This includes

  • Changing the return type
  • Changing the order of parameters
  • Change the access rights ( eg. public to protected)
  • removing or adding parameters

4. Add, remove, or re-order member variables in a class

5. Change the type of any member variable in a class

6. Change the class hierarchy  of the class exposed in your dll - for example, 

  • make the exposed class inherit from a different base class
  • make the exposed class  inherit from additional base classes
  • remove base class(es) from the exposed class

7. Change the template arguments (add, remove,r, re-order) of a templated class

  • this is in line with #3 above since changing the template arguments changes the underlying function signatures generated when the template is instantiated

8.  Inline a function in an exported class

  • When a function is declared inlined, the compiler inlines it where the function is called and may not generate an out-of-line copy. The client binary, which was thus far depending on the exported out-of-line function signature cannot locate it anymoe and will fail in unexpected ways (crash most likely).

9. Change the const or volatile qualifier of a member function

  • Some compilers encode the constness of a function in the mangled name and hence changing the function from const to non-const changes the mangled name.

10. Change the type of global data

11. Changing the const or volatile qualifiers on global data

12. Adding an explicit copy constructor or destructor to a class that would otherwise have implicit versions. ( Ref: https://gcc.gnu.org/onlinedocs/libstdc++/manual/abi.html)

13. Changing a non-virtual method to be virtual, and vice versa.

14. Adding a virtual method to a class with no existing virtual methods.

15. Changing the order of virtual methods.

16. Adding new virtual methods (some compilers may preserve binary compatibility if you only add new virtual methods after existing ones).

17. Override a virtual that doesn't come from a primary base

18. Remove a virtual function, even if it is a reimplementation of a virtual function from the base class

19. Change the calling convention of an exported function ( from _stdcall to _cdecl and vice versa)

20.  If passing C++ types across dll boundary, make sure that your client exe and dll are compiled with the same version of the compiler. There are often ABI breakages between different versions - like VS2012 and VS 2015.

Further Reading