2012-06-12 23 views
7

Ho condiviso l'oggetto A.so che collega staticamente a libssl.a & un altro oggetto condiviso B.so che collega anche staticamente libssl.a.Libreria statica caricata due volte

A.so & B.so ha simboli da libssl.a in ambito GLOBAL. L'ho controllato da me stesso -s A.so

Ho un eseguibile a.out che carica A.so e B.so. Alla fine di a.out, ricevo un doppio errore libero in uno dei simboli da libssl.a in A.so.

Anche se libssl.a è collegato staticamente a ciascun oggetto condiviso, poiché sono esposti a livello globale è possibile che lo stesso simbolo sia condiviso invece di prelevarne la copia locale.

Qual è la soluzione alternativa? Come rendere i simboli locali qui?

Si prega di aiutare

+0

Si consiglia di utilizzare un debugger per confermare la propria teoria. – jdigital

+0

Potresti elaborare? – KodeWarrior

+0

Solo una piccola cosa, perché non ho idea di come applicarlo alla tua situazione: 'dlopen' ha un flag RTLD_LOCAL che in alcune circostanze potrebbe aiutare proprio in questa situazione. Quindi se hai aperto quelle librerie con 'dlopen', probabilmente non dovrebbero interferire in quel momento. – liori

risposta

5

Questo è infatti previsto. Un'istanza di libssl.a interpone (probabilmente un sottoinsieme di) l'altro e i risultati non sono belli. È possibile utilizzare uno script di versione (--version-script a ld, con -Wl, per cc) per controllare ciò che viene esportato da A.so e B.so. Se qualcosa non viene esportato, non può nemmeno essere interposto.

In alternativa, è possibile compilare libssl.a con flag di visibilità come -fvisibility=hidden. Questi flag influenzano solo il linker dinamico e non il collegamento statico. Probabilmente è necessario compilarlo comunque perché i file spediti .a tendono a contenere codice dipendente dalla posizione, pensato per il collegamento a file eseguibili. Solo alcune piattaforme come x86 a 32 bit ti permettono di farla franca collegando tale codice a oggetti condivisi e solo a costo di trasferimenti di testo.

Il dlopen con RTLD_LOCAL come suggerito in un commento dovrebbe funzionare ma sembra logico utilizzare dlopen per questo scopo.

Un'altra opzione è utilizzare lo stesso libssl.so condiviso in entrambe le librerie.

Problemi correlati