Ú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:
Con el comando: 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:
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:
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:
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¶
- Funciones virtuales puras y clases abstractas en C++ | C++那些事
- Aserciones assert en C++ | C++那些事
- Campos de bits en C++ | C++那些事
- Implementar el polimorfismo de C++ en lenguaje C | C++那些事
- const en C++: constantes y modificación | C++那些事
- La familia completa de const en C++ | C++那些事
- El operador de desreferencia * en C++ | C++那些事
- Inicialización y asignación en C++ | C++那些事
- Formas de devolver varios valores en C++ | C++那些事
- La palabra clave mutable en C++ | C++那些事