Saltar a contenido

Última actualización:2026-10-12

Compatibilidad del ABI de string en C++

Problema real de proyecto: cómo evitar los problemas de compatibilidad del ABI de String en C++

¿Por qué a mucha gente no le gusta std::string de C++ y prefiere fabricar su propia rueda? Uno de los motivos es el problema del ABI de string en C++, ¿te has topado con él?

Antes, al usar Conan con bibliotecas multiplataforma, surgió un problema de compatibilidad del ABI de string en C++; esta sección presenta los antecedentes del ABI y contenidos relacionados con el compilador, y explica cómo evitar este pozo. Si te ha pasado, déjanos un comentario~!

1. Antecedentes del cambio de ABI

A partir de GCC 5.1 se reforzó el soporte de C++11 y se introdujeron algunas características nuevas. En esa versión, libstdc++ introdujo un nuevo ABI de biblioteca y actualizó las implementaciones de std::string y std::list. Estos cambios se ajustan al estándar C++11, que prohíbe las cadenas Copy-On-Write y exige que las listas enlazadas puedan rastrear su tamaño.

En proyectos reales, al usar Conan, quien desarrolla puede elegir el ABI ajustando compiler.libcxx:

  • libstdc++: usa el ABI antiguo.
  • libstdc++11: usa el ABI nuevo.

Elegir el ABI adecuado garantiza la compatibilidad con otras bibliotecas de las que se depende, especialmente cuando se usan versiones distintas del compilador o de las bibliotecas.

2. Configuración por defecto del compilador

Al compilar con GCC, si no se especifica explícitamente --with-default-libstdcxx-abi=gcc4-compatible, GCC usa por defecto el nuevo ABI de C++11. Esto significa:

  • Si tu código o las bibliotecas de las que dependes se compilaron con el ABI antiguo, al intentar enlazar puedes encontrarte con errores de símbolos no definidos.

Por ejemplo, al compilar el siguiente código:

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

g++-14 -D_GLIBCXX_USE_CXX11_ABI=0 -c lib.cc
Se generará el símbolo __Z3fooRKSs, que es el formato del ABI antiguo.

Sin embargo, al compilar y enlazar otro archivo que usa el ABI nuevo, puede aparecer un error como este:

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. Soluciones

Para asegurarte de que la compilación pase, hay dos soluciones:

Método 1: especificar el ABI manualmente

Al compilar todos los archivos fuente, asegúrate de añadir manualmente -D_GLIBCXX_USE_CXX11_ABI=0 para ser compatible con las bibliotecas antiguas, por ejemplo:

g++-14 -D_GLIBCXX_USE_CXX11_ABI=0 main.cc lib.o
Método 2: compilar todos los archivos con el ABI nuevo

Si te parece bien usar el nuevo ABI de C++11, puedes compilar los archivos de la biblioteca con -D_GLIBCXX_USE_CXX11_ABI=1, de modo que los símbolos de ambos coincidirán:

g++-14 -D_GLIBCXX_USE_CXX11_ABI=1 -c lib.cc
g++-14 main.cc lib.o
En este punto, los símbolos coincidirán al enlazar y ya no aparecerá el error de símbolos no definidos.

4. Comparación de símbolos

Consultando con el comando nm los símbolos bajo los distintos ABI, se pueden ver de un vistazo las diferencias entre ambos:

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. Resumen

El ABI es un pozo enorme con el que uno se encuentra al actualizar C++ y durante la compilación; espero que este artículo haya logrado explicar bien estos contenidos.

Temas relacionados

Comentarios