Hacker News new | ask | show | jobs
by eklitzke 2328 days ago
Every implementation implicitly defines an ABI due to the size and layout of classes/structs defined in the STL.

Here's a simple example. Suppose we define std::string with the following layout (for simplicity I'm removing the template stuff, SSO, etc.):

  class string {
   public:
    // various methods here...

    size_t size() const { return len_; }
 
   private:
    char *data_;
    size_t len_;
    size_t capacity_;
  };
When a user calls .size() on a string, the compiler will emit some inlined instructions that access the len_ field at offset +8 bytes into the class (assuming 64-bit system).

Now suppose we modify our implementation of std::string, and we want to change the order of the len_ and capacity_ fields, so the new order is: data_, capacity_, len_. If an executable or library links against the STL and isn't recompiled, it will have inlined instructions that are now reading the wrong field (capacity_).

This is what we mean by the C++ ABI. This is a simple example, but there are a lot of other changes that can break ABI this way.

1 comments

That's not exactly the same. What you're referring to is the library ABI for the c++ standard library. Every library which can be linked to dynamically has its own ABI. The language ABI, on the other hand, describes how every library's ABI is defined, describing things like layout and name mangling. So if, for instance, the language ABI were amended to say that class members are arranged in alphabetical order in memory, then capacity_ will always be at offset 0, data_ at offset 8, and len_ at offset 16; if you change the order of declarations then, the library's ABI won't change. But if the library were compiled with an old compiler that targeted the old ABI, then it would put data_ first, followed by len_, then capacity_. So if you then compiled a new piece of code with a new compiler targeting the new ABI, but linked against it the library, there would be a mismatch.