Estou compilando um aplicativo no macOS 15.4 com o Xcode 16.1. Ao examinar os arquivos de objeto produzidos pelo compilador, alguns símbolos foram [abi:de180100]
anexados a eles. Este sufixo não está no código C++. Parece que este sufixo também está sendo anexado a vários outros símbolos e projetos.
Gostaria de saber mais sobre o sufixo, por que ele é necessário e quais são suas implicações para o símbolo que ele qualifica. No entanto, não consigo encontrar nenhuma documentação sobre ele em lugar nenhum. Alguém pode me indicar o caminho certo?
O
[abi:de180100]
apêndice é umalibc++
tag ABI (Application Binary Interface).libc++
é a implementação LLVM/clang da biblioteca C++ padrão, correspondente ao GNU/GCClibstdc++
A tag
de180100
é a concatenação de três valores definidos por macros do pré-processador nolibc++
arquivo de cabeçalho de configuração (por exemplo/usr/lib/llvm-18/include/c++/v1/__config
):_LIBCPP_HARDENING_SIG
=f
,s
,d
oun
, +_LIBCPP_EXCEPTIONS_SIG
=n
oue
+_LIBCPP_VERSION
= número de série da versão libc++._LIBCPP_HARDENING_SIG
codifica o modo de proteção da biblioteca. Um modo de proteção é um nível de imposição das pré-condições da biblioteca, implementado por meio de asserções. Os modos de proteção são explicados aqui._LIBCPP_EXCEPTIONS_SIG
codifica se as funções da biblioteca podem (e
) ou não (n
) sinalizar falha lançando uma exceção.Então você está usando
libc++
a versão180100
, configurada com modo de proteçãod
( =Debug mode
) e com lançamento de exceção habilitado.A tag ABI assim concatenada é chamada
_LIBCPP_ODR_SIGNATURE
de configuração da biblioteca. Os comentários no__config
cabeçalho explicam esta macro:A representação
[abi::de180100]
é a representação desmantelada. No símbolo do linker mutilado, aparece como o sufixoB8de180100m
O compilador aplicará essa tag a um símbolo quando o símbolo for declarado no código-fonte com
__attribute__((__abi_tag__(_LIBCPP_ODR_SIGNATURE)))
. (Você não encontrará essa string executando grep nos seuslibc++
arquivos de cabeçalho, porque ela é gerada a partir da expansão de outras macros do pré-processador.)Você, como usuário da biblioteca, normalmente não implementará essa tag ABI no código que escreve (embora nada o impeça). O código-fonte em questão será um código de modelo que você incluiu de um dos arquivos de cabeçalho C++ padrão do clang. Um símbolo com a tag ABI
_LIBCPP_ODR_SIGNATURE
definirá uma instanciação embutida de alguma função (membro) de modelo de biblioteca C++ e terá uma ligação global fraca, o que significa que o vinculador ingerirá múltiplas definições do símbolo sem falhas e escolherá uma arbitrariamente. O símbolo tem a tag ABI porque essas definições embutidas globais fracas são justamente aquelas para as quais surge o risco à integridade do ODR.Se você se pergunta por que instanciações embutidas de funções de modelo são compiladas com vinculação global fraca (seja por clang ou GCC), você pode consultar minha resposta em Como o vinculador lida com instanciações de modelo idênticas em unidades de tradução?, onde eu deliberadamente violei o ODR para demonstrar a resposta.
E para um mergulho mais profundo no uso de tags ABI no policiamento da compatibilidade da biblioteca padrão ABI do C++, você pode ver Compatibilidade da biblioteca padrão ABI do C++ , um dos blogs do Maskray.
A propósito, você não precisa ter essa proteção se não quiser. Se você compilar TUs com
-D_LIBCPP_NO_ABI_TAG
então o clang entenderá a dica.