Sto sperimentando la visibilità dei simboli C++ su Linux e gcc. Sembra che il modo preferito sia usare -fvisibility = hidden e esportare i simboli usati uno per uno in base alla pagina wiki di gcc Visibility (http://gcc.gnu.org/wiki/Visibility). Il mio problema è che molte librerie non gestiscono bene questo, si dimenticano di esportare esplicitamente simboli, che è un problema serio. Dopo diversi bug risolti, anche alcune parti di boost potrebbero essere influenzate. Ovviamente questi bug dovrebbero essere corretti, ma fino a quel momento mi piacerebbe usare un modo "sicuro" per nascondere il più possibile i simboli.Visibilità dei simboli e spazio dei nomi
Mi è venuta una soluzione: inserisco tutti i simboli in un namespace e utilizzo l'attributo symbol hide su questo ed esporta l'interfaccia pubblica, in questo modo solo i miei simboli possono essere influenzati.
Il problema è che ho ricevuto un messaggio di avviso quando compilo qualcosa contro quella libreria per ogni classe che non ho esportato e che utilizzo nell'applicazione come campo della classe.
namespace MyDSO __attribute__ ((visibility ("hidden"))) {
struct Foo {
void bar() __attribute__ ((visibility ("default"))) {}
};
}
struct Bar {
MyDSO::Foo foo;
};
int main() {}
Il messaggio di avviso possono essere riprodotti in questo piccolo esempio, ma naturalmente lo spazio dei nomi dovrebbe essere in una libreria l'altra classe nell'applicazione.
$ gcc-4.7.1 namespace.cpp -o namespace
namespace.cpp:7:8: warning: ‘Bar’ declared with greater visibility than the type of its field ‘Bar::foo’ [-Wattributes]
quanto ho capito visibilità simbolo, nascondendo namespace dovrebbe avere effetto del tutto simile all'uso -fvisibility = nascosto, ma non ho mai avuto avvertimenti simili utilizzando quest'ultimo. Vedo che quando passo -fvisibility = nascosto all'applicazione anche la classe nell'applicazione sarà nascosta, quindi non avrò un avvertimento. Ma quando non passo l'opzione nessuno dei simboli nelle intestazioni sembrerà nascosto al compilatore, quindi non avrò più un avviso.
Qual è la proposta di questo messaggio di avviso? È un problema serio? In quali situazioni questo può causare problemi? Come nascondere lo spazio dei nomi è diverso da fvisibility = hidden?
Grazie per la tua risposta dettagliata. Solo per curiosità, mi interessa quali sono i simboli necessari al compilatore che non possono essere generati? Per quanto ne sappia nelle classi banali anche il typeinfo può essere generato. Quando si utilizza vis = hidden non si ottiene un avviso anche quando si nascondono simboli che non devono essere nascosti, si ottiene un errore di simbolo non definito dal linker. Usando lo spazio dei nomi nascosto gcc può rilevare il problema. Forse c'è un uso legittimo di esportare solo alcuni simboli in una classe, ma gcc emette comunque un avviso. I moduli C++ di Doug Gregor sono molto interessanti, mi è piaciuta la sua presentazione, grazie per averlo condiviso. – VargaD
In breve, digitareinfo per qualsiasi classe con un virtual viene sempre emesso, mentre typeinfo per le classi senza viene emesso solo quando typeid() o qualcosa che lo utilizza (eccezioni catch, dynamic_cast <> etc) viene utilizzato. Inoltre, la maggior parte dei compilatori emette due o più implementazioni del costruttore per ogni programma di costruzione specificato, e c'è anche della magia nella generazione del distruttore. In breve, -fvisibility = hidden nasconde il lotto, e il tuo metodo nasconderebbe solo le cose specificate dal programmatore e non gli interni magici. Molto di questo comincia a diventare più semplice con i moduli C++, anche se non è affatto risolto. Niall –