Home > Blockchain >  Singleton and ABI stability
Singleton and ABI stability

Time:07-02

Consider the following class

// in library 
class A {
  public:
    static A* instance(){
       static A self;
       return &self;
    }
    void foo() { }
  private:
    A () {}
    int a{0};
};

that is defined in dynamic library.

Then a new version of the class is defined with an extra field b.

class A {
  // as before
  private:
   
    int b{0};
};

Is the new version of the library breaking the ABI ?

For a regular class, I would say yes undoubtedly, but for a singleton I think it's /not/ a ABI break (the application handles only pointers to A which didn't changed, nothing public changed). But I'm not sure and I would like a definitive answer.

CodePudding user response:

If the application code ever needs a complete type for A in order to compile, then yes this would be an ABI break.

If the application merely stores a pointer to A (and calls into the library to obtain an A*) then there is no ABI break.

Comparisons can be made here with the FILE* pointer of C.

The fact that A is a singleton is a red herring.

CodePudding user response:

Yes, it is.

First, with regards to guarantees by the standard, changing any single token in the class definition requires all translation units (including libraries) to use the new definition in order to not break the ODR and cause undefined behavior.

Obviously there are situations in practice where you can rely on the implementation-specific behavior to still make it work and not break ABI in the practical sense.

In the case you are showing, at the very least the instance function will be a problem. This function is an inline function and must know the actual exact layout of A. But because it is an inline function you cannot control that both the library and the library user will use the same version of this function. You can easily get a mismatch and then the object might be constructed with the wrong layout.

Even if you make instance non-inline, you will have the same issue with the constructor which is also inline in your code.

  • Related