Pergunta

I tem uma plataforma transversal C ++ aplicação que está dividido em várias bibliotecas e cargas de funcionalidade adicional para dividir a partir de encaixe bibliotecas compartilhadas. As bibliotecas de plug-in é suposto ser auto-contido e função por si só, sem o conhecimento ou a dependência do aplicativo de chamada.

Um dos plugins contém o código do aplicativo principal copiado, então contém nomes de símbolos que são duplicado aos do motor. (Sim, eu sei que é geralmente um não-não, mas no momento em que o plugin foi escrito o motor era um binário monolítica e não podia compartilhar bibliotecas.) No Windows, tudo corre bem. No Linux que iríamos conseguir segfaults. Ao olhar para o rastreamento de pilha do erro, ele estava ocorrendo no plugin ao chamar funções no nome da classe duplicado. Parecia ser um resultado do motor e plug-in ter ligeiramente diferentes versões do código compartilhado (algumas funcionalidades classe foi comentada no plugin). Era como se o plugin estava entendendo de símbolos de tempo de execução ligada ao motor é em vez do seu próprio. Nós "fixa" o problema alterando os parâmetros do dlopen ser dlopen(pFilepath, RTLD_LAZY | RTLD_LOCAL).

Mas quando reescrevemos o motor a ser dividido em bibliotecas compartilhadas (para o eventual objetivo de reutilização nos plugins), obtemos o erro segfault novamente. E olhando para o rastreamento de pilha, que vai do motor -> plugin -.> Motor

Existe uma maneira de especificar para o vinculador tempo de execução para não mapear símbolos do plugin para o motor (especialmente se eles são definidos no plugin)?

Obrigado! Matt


Editado 2009/12/03

A primeira vez que tentou envolver o código do plugin no seu próprio namespace. Isso não funcionou porque é estaticamente ligado a uma biblioteca que também está ligada ao motor. As versões da biblioteca estática são diferentes, então segfault!

Então eu mudei a construção do motor e é bibliotecas de ser ligado estaticamente. E quando eu executá-lo, eu não tenho mais a questão. Assim, parece que era um resultado de ter os símbolos de bibliotecas compartilhadas exportadas e depois ser realocados dinamicamente para o plug-in quando foi aberto. Mas quando todo o código do motor está em um único executável, ele não exporta seus símbolos (para que ele não tente mudar símbolos do plugin para o motor).

Eu ainda tenho um problema, porém, como há uma versão paralelizado do programa (usando Open-MPI) e que ainda recebe o segfault. Aparece em que ele ainda está exportando símbolos do motor e relocação do plugin. Isso pode ter a ver com a forma como Open-MPI executa a aplicação.

Existem bandeiras vinculador que poderiam ser usados ??na biblioteca compartilhada plugin que iria dizer não para dinamicamente mudar os símbolos em tempo de execução? Ou para escondê-lo de símbolos para que eles não se movido? Eu tentei -s ( "Omitir todas as informações símbolo"), mas que aparentemente não altera os símbolos dinâmicas (verificado usando nm -D <plugin>).

Foi útil?

Solução

Eu acho que eu encontrei a solução, o -Bsymbolic sinalizador de vinculador. Essencialmente, este sinalizador adiciona uma bandeira na biblioteca compartilhada para dizer ao linker de tempo de execução para tentar símbolo resolver nomes dentro de si mesmo em primeiro lugar. O motor era capaz de correr com o plugin muito bem em todos os casos (exe monolítico, exe w / bibliotecas compartilhadas, de encaixe w / e w / o envolvendo o namespace) quando o plugin foi ligada com a bandeira.

Não parece haver alguns detratores com avisos sobre -Bsymbolic:
http://www.technovelty.org/code/c/bsymbolic.html
http://software.intel.com/en-us/articles/performance-tools-for-software-developers-bsymbolic-can-cause-dangerous-side-effects/

Mas, considerando as suas advertências e qual é a intenção do plugin é, eu acho que é a opção certa para mim. Pelo menos por agora.

Outras dicas

Eu concordo com Glen - você não está indo para realmente resolver este a menos que você modificar os nomes de classe, possivelmente através de namespaces. Até 36 arquivos provavelmente levará menos tempo para modificar do que tentar corrigi-lo de forma confiável sem alterar nomes de símbolo.

Comece por identificar todas as classes cujos nomes precisam ser mexido. Seu vinculador provavelmente relaciona-los para você já. Então, eu mudaria os nomes de ambos conjuntos de aulas (de Foo a Motor :: Foo e Plugin :: Foo por exemplo), pelo menos temporariamente. Dessa forma, você pode obter o compilador para encontrar todas as referências para as classes problemáticas. Chug afastado na fonte plug-in até que os compila plugin com referências aos nomes novos corretas classe plugin. Uma vez feito isto, mudar o motor :: aulas de volta para seus nomes antigos (a menos que você deseja modificar permanentemente fonte motor também, que parece que você não). O plugin deve agora compilar e link para as corretas, classes com nomes exclusivos.

Gostaria apenas de envolver todo o código do plugin com um namespace PluginX. Que certamente irá poupar-lhe a partir desses erros. É um muito bom, importante, a prática de qualquer maneira.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top