libstdc++ c++98 & c++11 ABI incompatibility

Matthias Klose doko@ubuntu.com
Thu Jun 14 13:14:00 GMT 2012


While PR53646 claims that c++98 and c++11 should be ABI
compatible (modulo bugs), the addition of the _M_size member
to std::_List_base::_List_impl makes libraries using
std::list in headers incompatible, when built in c++98 and
c++11 mode.  Currently seen in libsigc++ (Signal Framework
for C++) and libapt-pkg (Debian package management).

sigc++/signal_base.h:

struct SIGC_API signal_impl
{
  typedef size_t size_type;
  typedef std::list<slot_base> slot_list;
  typedef slot_list::iterator       iterator_type;
  typedef slot_list::const_iterator const_iterator_type;

  signal_impl();
[...]

apt-pkg/error.h:

class GlobalError
{
[...]
        std::list<Item> Messages;
        bool PendingFlag;

Inline-ing code accessing these members gets the offset wrong.
For apt this probably can be changed so that it works in both
modes, but it gets more difficult for software which is not
controlled by the distribution like libsigc++.  I'll check
the archive for more occurrences of such code.

Looking at the build logs for packages built by a distribution,
I see that a lot of packages already build in c++0x/c++11 mode,
while the majority still uses the c++98 default. The GCC
documentation says "Support for C++11 is still experimental,
and may change in incompatible ways in future releases",
however upstream authors already use it by default (e.g.
LibreOffice).

So what could be done for a distribution?

 - For this particular issue, ask upstreams to work around this
   particular incompatibility.  This might work better, if the
   upstream sits "closer" to the distribution, but doesn't seem
   to be a general solution.

 - Identify all libraries with this incompatibility, and build
   the library twice for each mode. That would need a new soname
   when built in c++11 mode (which better should be done upstream
   first), and some logic to link with the c++11 library when
   building in c++11 mode.  But I don't think that distributions
   want to build and maintain a second c++ stack.

 - Build all packages in c++98 mode or in c++11 mode.  Because
   c++11 is still experimental, this would be c++98 mode.  But
   then c++11-only software would need removal from the
   distribution if a dependent library is only available in c++98
   mode. Or an internal copy of a library could be built in
   c++11 mode.

I currently tend to the latter approach, but would like to get
some feedback about other alternatives.

And is there a way to tell which mode a shared object/an
executable was built for, when just looking at the stripped
or unstripped object?

  Matthias



More information about the Libstdc++ mailing list