Ú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:
Com o comando:
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:
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:
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:
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¶
- Funções virtuais puras e classes abstratas em C++ | C++那些事
- Asserções com assert em C++ | C++那些事
- Bit fields em C++ | C++那些事
- Implementando polimorfismo de C++ em linguagem C | C++那些事
- Constantes e modificadores com const em C++ | C++那些事
- A família completa do const em C++ | C++那些事
- O operador de desreferência * em C++ | C++那些事
- Inicialização e atribuição em C++ | C++那些事
- Formas de retornar múltiplos valores em C++ | C++那些事
- A palavra-chave mutable em C++ | C++那些事