In che modo i file .so evitano problemi associati al passaggio di modelli di sola intestazione come quelli di MS dll?

4

Basato sulla discussione intorno a questa domanda . Mi piacerebbe sapere come i file .so / il formato ELF / la toolchain gcc evitano problemi nel passare classi definite esclusivamente nei file di intestazione (come la libreria std). Secondo Jan in quella risposta, il linker / loader dinamico sceglie solo una versione di tale classe da caricare se è definita in due file .so. Quindi se due file .so hanno due definizioni, forse con opzioni di compilatore / etc diverse, il linker dinamico può sceglierne uno da usare.

È corretto? Come funziona con l'inlining? Ad esempio, MSVC inline modelli in modo aggressivo. Ciò rende insostenibile la soluzione che ho descritto sopra per le DLL. GCC non inserisce mai modelli di solo intestazione come la libreria std come fa MSVC? Se così fosse, non renderebbe la funzionalità di ELF sopra descritta inefficace in questi casi?

    
posta Doug T. 21.11.2012 - 16:43
fonte

2 risposte

7

Ciò che fa il linker ELF è che garantisce che il linker statico e dinamico produca lo stesso risultato. Quindi, usare gli oggetti condivisi non crea nuovi problemi. Puoi crearne alcuni se usi visibilità o versione o script linker non predefiniti, ma ovviamente non lo faresti se non è sicuro in quel caso particolare.

Ora se usi set incompatibili di flag di compilazione per creare oggetti diversi, sia condivisi che statici, in una applicazione, avrai dei problemi. Puoi avere due tipi di problemi:

  • I flag sono così incompatibili che la convenzione di chiamata, il layout della struttura o qualche altro parametro di questo tipo è diverso tra i moduli. Ovviamente l'unica soluzione è sapere quali opzioni del compilatore devono sempre essere impostate sui valori predefiniti della piattaforma.

  • I flag modificano il contenuto delle intestazioni e quindi violano una regola di definizione. Gli autori di librerie standard, almeno quelle open source, sanno bene come evitare la rottura della compatibilità tra gli oggetti. Ma se hai una libreria speciale a cui l'autore non fa attenzione, puoi metterti nei guai e assicurarti che i flag di compilazione siano compatibili.

In Linux non ho visto succedere questi problemi. Tutti sanno di non toccare i flag del compilatore che potrebbero rompere nulla e non ci sono versioni incompatibili speciali per il debug o simili (gcc può emettere informazioni di debug nell'ottimizzazione della build, quindi normalmente si ottiene semplicemente la versione non stoppata dello stesso oggetto o ultimamente anche solo il debug informazioni per l'oggetto normale divisi in file separati).

Questo è diverso da Windows, dove:

  • A causa del modo in cui le librerie condivise necessitano di esportazione e importazione esplicite, non si uniranno simboli (come istanze di template o impedimenta di classe) generati in diverse librerie condivise.
  • Avere debug separati e release runtime che differiscono sia nella libreria condivisa utilizzata che nel lotto della magia del preprocessore. Significa che non è possibile collegare la build di debug alle librerie create con la versione di rilascio, quindi ogni libreria deve fornire la versione di debug e release. E spesso variante per il collegamento statico e dinamico. E nonostante tutti questi problemi, non penso che il supporto per il debug su Windows sia migliore; per esempio. Linux libc ha dei ganci per sostituire l'allocatore (con debug uno) che è sempre macroscopico su Windows e Linux ha grandi strumenti come Valgrind.
  • Molti flag del compilatore vengono capovolti per vari motivi di compatibilità, causando ulteriori complicazioni. Va detto che Microsoft è in una posizione più difficile qui. Dal momento che si rivolgono principalmente ai programmatori a codice chiuso, devono supporre che le cose non possano essere ricompilate e debbano fornire vari kludges di compatibilità per far funzionare le cose. Le persone Linux presumono che le cose possano essere ricompilate e cambino quando le cose diventano troppo complicate, come lo era il passaggio al formato ELF; Il formato ELF è stato creato tra il 1997 e il 1999, mentre gli oggetti Windows sono ancora retrocompatibili con quelli precedenti di Windows 3.1. Al costo di tutto il caos.
risposta data 22.11.2012 - 08:48
fonte
1

Non sono sicuro di aver capito. Se crei parti del tuo programma con diversi flag non compatibili, non si tratta di problemi .so o .dll, gli stessi problemi appariranno anche con le librerie statiche.

Innanzitutto, ho smesso di programmare per Windows nel 94. Quindi quasi tutte le mie conoscenze sul comportamento di Windows provengono dalla rete e discussioni con colleghi che lavorano su Windows e potrebbero essere obsoleti, miserrembered fatti male compresi.

  • È consuetudine su Windows includere la libreria standard in .DLL. Questo non è il caso su Unix (e ho capito che non è obbligatorio su Windows).

  • La risoluzione dei simboli di default su Windows preferisce la DLL, su Unix sarà la ricerca normale (in entrambi, puoi cambiarla).

  • È considerata una cattiva pratica su Unix creare librerie di debug che non sono sostituibili con quella ottimizzata. Sì, questo limita la strumentazione che può essere fatta, ma rende molte cose più facili. Potremmo fare speciali librerie strumentate che richiedono una ricompilazione totale quando ne valgono la pena, ma non è il caso delle routine di debug di routine. La mia comprensione è che il compilatore MSC ++ viene fornito con alcune librerie che non sono sostituibili se si compila il codice utente in debug o ottimizzato (ho ascoltato storie horror con #defining nuovo per esempio, che mi sembra una pessima idea anche per strumenti speciali costruisce). Niente di Windows ti costringe a fare questa pratica sbagliata (ma se la libreria standard di C ++ è in quel caso, probabilmente devi usare una libreria standard saner).

risposta data 21.11.2012 - 17:27
fonte

Leggi altre domande sui tag