Aqui está o cenário:
- libA.so e libB.so se vinculam estaticamente à mesma STL.
- libA.so possui uma API pública que retorna uma std :: string.
- libB.so chama essa função e recebe uma cópia da string.
- Quando a cópia do libB.so da string sai do escopo, o destruidor da string é chamado.
- O aplicativo seg falha ao tentar liberar a sequência copiada.
Eu li em outro lugar que vincular estaticamente assim é ruim, mas eu gostaria de entender melhor por que é ruim. Alguém pode explicar por que a sequência acima falharia?
c++
libraries
stl
static-linking
user1509041
fonte
fonte
Respostas:
Vamos pensar sobre isso com muito cuidado. O libA.so está estaticamente vinculado ao STL. No entanto, o STL não existe isoladamente, requer o tempo de execução C (CRT). Ambos residem na libstdc ++. Uma biblioteca estática. Isso significa que libA.so e libB.so possuem estruturas de dados CRT separadas. Em particular, o heap usado pelo libA.so é diferente do heap usado pelo libB.so. Alocar uma string do heap de tempo de execução da libA e tentar liberar o tempo de execução da libB simplesmente não funcionará porque o tempo de execução da libB não possui registros de alocação da string. A única maneira de destruir corretamente a string é chamando o destruidor no libA.so.
Alguém pode perguntar: mas libB.so recebe uma cópia da string, certo? Sim, está certo, mas quem alocou esta cópia? Ele foi alocado usando o construtor de cópia no contexto do tempo de execução da libA.
Dito isto, você ainda pode usar a sequência de libB.so. Você simplesmente não pode destruí-lo a partir daí.
Você também pode permitir que a libB receba um ponteiro para a string e, em seguida, crie uma cópia dela dentro do contexto do tempo de execução da libB. Essa cópia pode ser destruída pelo libB.
E é por isso que a vinculação estática às vezes é ruim.
fonte
std::string
, o problema simplesmente não existe: oulibB.so
recebe uma cópia da sequência, com a memória gerenciada em sua própria memória, ou recebe uma referência / ponteiro para a sequêncialibA.so
e não tenta remover a sequência de sua própria memória.O STL é chamado de "estado cheio" (em oposição a ser "sem estado"), o que significa que possui algumas coisas estáticas no interior. Ao vincular o STL estaticamente ao libA.so e libB.so, você obtém duas instâncias da biblioteca STL na memória em tempo de execução (com duas cópias de material estático). Cada uma dessas duas cópias gerencia recursos alocados de forma independente e os recursos alocados em uma instância da biblioteca não podem ser liberados em outra
fonte