Ir para o conteúdo

Última atualização:2026-10-12

Compatibilidade de ABI de string em C++

Problema de projeto do mundo real: como evitar as armadilhas de compatibilidade de ABI da string do C++

Por que muita gente não gosta da string do C++ e prefere reinventar a roda? Um dos motivos é o problema de ABI da string do C++ — você já se deparou com ele?

Anteriormente, ao usar o Conan com bibliotecas multiplataforma, ocorreu um problema de compatibilidade de ABI da string do C++. Esta seção apresenta o contexto do ABI e conteúdos relacionados ao compilador, e explica como evitar essa armadilha. Se você já passou por isso, deixe um comentário~

1. Contexto das mudanças de ABI

A partir do GCC 5.1, o suporte ao C++11 foi reforçado e alguns novos recursos foram introduzidos. Nessa versão, a libstdc++ introduziu uma nova ABI de biblioteca, atualizando as implementações de std::string e std::list. Essas mudanças estão em conformidade com o padrão C++11, que proíbe strings com Copy-On-Write e exige que listas encadeadas rastreiem o próprio tamanho.

Em projetos reais, ao usar o Conan, o desenvolvedor pode escolher a ABI a ser usada ajustando compiler.libcxx:

  • libstdc++: usa a ABI antiga.
  • libstdc++11: usa a nova ABI.

Escolher a ABI adequada garante compatibilidade com as demais bibliotecas dependentes, especialmente ao usar versões diferentes de compiladores ou bibliotecas.

2. Configuração padrão do compilador

Ao compilar com o GCC, se --with-default-libstdcxx-abi=gcc4-compatible não for especificado explicitamente, o GCC usa por padrão a nova ABI do C++11. Isso significa que:

  • Se o seu código ou as bibliotecas dependentes foram compilados com a ABI antiga, você pode encontrar erros de símbolo indefinido ao tentar vincular.

Por exemplo, ao compilar o seguinte código:

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

Com o comando:

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

Será gerado o símbolo __Z3fooRKSs, que é o formato da ABI antiga.

No entanto, ao compilar e vincular outro arquivo que usa a nova ABI, pode surgir um erro 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. Soluções

Para garantir que a compilação passe, há duas soluções:

Método 1: especificar a ABI manualmente

Ao compilar todos os arquivos-fonte, certifique-se de adicionar manualmente -D_GLIBCXX_USE_CXX11_ABI=0 para compatibilidade com bibliotecas antigas, por exemplo:

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

Método 2: compilar todos os arquivos com a nova ABI

Se você puder usar a nova ABI do C++11, compile os arquivos da biblioteca com -D_GLIBCXX_USE_CXX11_ABI=1; assim, os símbolos dos dois lados passarão a corresponder:

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

Nesse caso, os símbolos corresponderão na vinculação e o erro de símbolo indefinido deixará de ocorrer.

4. Comparação de símbolos

Com o comando nm, é possível ver os símbolos nas diferentes ABIs e visualizar claramente a diferença entre elas:

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

A ABI é uma armadilha enorme encontrada nas atualizações do C++ e no processo de compilação; espero que este artigo tenha conseguido explicar bem esses conteúdos.

Tópicos relacionados

Comentários