Skip to content

Last updated:2026-10-12

C++ string ABI Compatibility

A Real-World Project Problem: Avoiding the C++ String ABI Compatibility Pitfall

Why do many people dislike C++ string and reinvent the wheel instead? One of the reasons is the C++ string ABI problem — have you ever run into it?

I previously hit a C++ string ABI compatibility problem while using Conan with cross-platform libraries. This section introduces the background of ABI and compiler-related content, and talks about how to avoid this pitfall. If you have run into it, feel free to leave a comment~

1. Background of the ABI Change

After GCC 5.1, support for C++11 was strengthened and some new features were introduced. In that release, libstdc++ introduced a new library ABI and updated the implementations of std::string and std::list. These changes conform to the C++11 standard, which forbids Copy-On-Write strings and requires lists to be able to track their size.

In real projects using Conan, developers can choose which ABI to use by adjusting compiler.libcxx:

  • libstdc++: uses the old ABI.
  • libstdc++11: uses the new ABI.

Choosing the appropriate ABI ensures compatibility with other dependency libraries, especially when using different versions of compilers or libraries.

2. Compiler Default Settings

When compiling with GCC, if --with-default-libstdcxx-abi=gcc4-compatible is not explicitly specified, GCC uses the new C++11 ABI by default. This means:

  • If your code or dependency libraries were compiled under the old ABI, you may encounter undefined-symbol errors when you try to link.

For example, when compiling the following code:

// lib.cc
#include <string>
void foo(const std::string& s) {}

Using the command:

g++-14 -D_GLIBCXX_USE_CXX11_ABI=0 -c lib.cc

This generates the symbol __Z3fooRKSs, which is the old ABI format.

However, when you compile and link another file that uses the new ABI, an error like the following may appear:

g++-14 main.cc lib.o
Undefined symbols for architecture x86_64:
  "foo(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)", referenced from:
      _main in ccbWGoYh.o
ld: symbol(s) not found for architecture x86_64
collect2: error: ld returned 1 exit status

3. Solutions

To make the compilation pass, there are two solutions:

Option 1: Manually specify the ABI

When compiling all source files, make sure to manually add -D_GLIBCXX_USE_CXX11_ABI=0 for compatibility with the old library, for example:

g++-14 -D_GLIBCXX_USE_CXX11_ABI=0 main.cc lib.o

Option 2: Compile all files with the new ABI

If you are willing to use the new C++11 ABI, you can use -D_GLIBCXX_USE_CXX11_ABI=1 when compiling the library file, so that the two symbols match:

g++-14 -D_GLIBCXX_USE_CXX11_ABI=1 -c lib.cc
g++-14 main.cc lib.o

Now the symbols match at link time, and the undefined-symbol error no longer appears.

4. Symbol Comparison

By viewing the symbols under the different ABIs with the nm command, you can see the difference between the two directly:

g++-14 -D_GLIBCXX_USE_CXX11_ABI=0 -c lib.cc
nm lib.o | grep foo  
# 输出: 0000000000000000 T __Z3fooRKSs

g++-14 -D_GLIBCXX_USE_CXX11_ABI=1 -c lib.cc
nm lib.o | grep foo  
# 输出: 0000000000000000 T __Z3fooRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE

5. Summary

ABI is a huge pitfall encountered when upgrading C++ and during compilation; I hope this article makes these things clear.

Comments