L'indirizzo di C ++ 11 riguarda il passaggio di oggetti lib di std tra i contorni di librerie dinamiche / condivise? (cioè dlls e così)?

30

Uno dei miei principali reclami su C ++ è quanto sia difficile in pratica passare gli oggetti della libreria std al di fuori dei limiti della libreria dinamica (cioè dll / so).

La libreria std è spesso solo di intestazione. Il che è ottimo per fare alcune fantastiche ottimizzazioni. Tuttavia, per dll, sono spesso costruiti con diverse impostazioni del compilatore che possono avere un impatto sulla struttura / codice interno di un contenitore di libreria standard. Ad esempio, in MSVC è possibile creare una dll con il debug di iterator mentre un'altra build viene disattivata. Queste due DLL potrebbero incappare in problemi con i contenitori std in giro. Se espoziono std::string nella mia interfaccia, non posso garantire che il codice utilizzato dal client per std::string sia una corrispondenza esatta del std::string della mia libreria.

Questo porta a problemi di debug, mal di testa, ecc. È possibile controllare rigidamente le impostazioni del compilatore nella propria organizzazione per prevenire questi problemi o utilizzare un'interfaccia C più semplice che non presenterà questi problemi. Oppure specifica ai tuoi clienti le impostazioni del compilatore che dovrebbero usare (che fa schifo se un'altra libreria specifica altre impostazioni del compilatore).

La mia domanda è se C ++ 11 ha provato a fare qualcosa per risolvere questi problemi?

    
posta Doug T. 21.11.2012 - 14:47
fonte

3 risposte

18

Hai ragione nel dire che qualsiasi cosa STL - in realtà, qualsiasi cosa proveniente da qualsiasi libreria di terze parti che è basata su modelli - è meglio evitare in qualsiasi API C ++ pubblica. Vuoi anche seguire la lunga lista di regole al link per inibire la rottura di ABI che rende la programmazione pubblica API C ++ un lavoro di routine.

E la risposta riguardo al C ++ 11 è no, questo standard non sta toccando quello. Più interessante è perché no? La risposta è perché il C ++ 17 è molto toccante, e per i moduli C ++ da implementare abbiamo bisogno di template esportati per funzionare, e per questo abbiamo bisogno di un compilatore di tipo LLVM come clang che può scaricare l'intero AST su disco e quindi fare ricerche dipendenti dal chiamante per gestire i numerosi casi di violazione di ODR in qualsiasi progetto C ++ di grandi dimensioni - che, tra l'altro, include molti codici GCC ed ELF.

Infine, vedo molti commenti di odio e pro-GCC da parte di MSVC. Questi sono molto disinformati - GCC su ELF è fondamentalmente, e irrimediabilmente, incapace di produrre codice C ++ valido e corretto. Le ragioni di ciò sono molte e legion, ma citerò rapidamente un caso: GCC su ELF non può produrre estensioni Python scritte usando Boost.Python dove più di un'estensione basata su Boost.Python viene caricata in Python. Questo perché ELF con la sua tabella dei simboli C globale è semplicemente incapace di impedire che le violazioni ODR causino segfaults, mentre PE e MachO e le specifiche dei moduli C ++ proposti utilizzano tutte tabelle di simboli per modulo - che per inciso significa anche tempi di avvio del processo molto più veloci. E ci sono molti più problemi: vedere uno StackOverflow che ho risposto di recente a link ad esempio dove i lanci di eccezioni C ++ sono irrimediabilmente infranti in ELF.

Ultimo punto: per quanto riguarda l'interferenza di diversi STL, questo è un grosso problema per molti grandi utenti aziendali che cercano di combinare librerie di terze parti strettamente integrate con alcune implementazioni STL. L'unica soluzione è un nuovo meccanismo per C ++ per gestire l'interoperabilità STL e, mentre ci sono, si potrebbe anche correggere l'interoperabilità del compilatore in modo da poter (ad esempio) mixare MSVC, GCC e clang file oggetto compilati e tutto funziona correttamente . Guarderei lo sforzo del C ++ 17 e vedrò cosa ci sarà nei prossimi anni - sarei sorpreso se nulla fosse.

    
risposta data 17.01.2013 - 17:58
fonte
8

Le specifiche non hanno mai avuto questo problema. Questo perché ha un concetto chiamato "una regola di definizione", che stabilisce che ogni simbolo abbia esattamente una definizione nel processo in esecuzione.

Le DLL di Windows violano questo requisito. Ecco perché ci sono tutti questi problemi. Quindi tocca a Microsoft risolverlo, non il comitato di standardizzazione del C ++. Unix non ha mai avuto questo problema, perché le librerie condivise funzionano in modo diverso lì e per impostazione predefinita sono conformi a una regola di definizione (puoi romperle esplicitamente, ma ovviamente lo fai solo se sai che puoi permetterti e devi spremere i pochi cicli extra).

Le DLL di Windows violano una regola di definizione perché:

  • Sono hardcode da cui viene utilizzata una libreria dinamica durante il tempo di collegamento statico e risolvono staticamente i simboli all'interno della libreria che li definisce. Pertanto, se lo stesso simbolo debole viene generato in più librerie condivise e in quelle librerie anziché essere utilizzato in un singolo processo, il linker dinamico non ha alcuna possibilità di unire tali simboli. Solitamente tali simboli sono membri statici o impedimenti di classe delle istanze di template e questo causa problemi durante il passaggio di istanze tra codice in DLL diverse.
  • Esse codificano automaticamente se il simbolo verrà importato dalla libreria dinamica già durante la compilazione. Quindi il codice collegato staticamente con alcune librerie è incompatibile con il codice collegato dinamicamente alla stessa libreria.

Unix che utilizza le esportazioni in formato ELF importa implicitamente tutti i simboli esportati per evitare il primo problema e non fa distinzione tra i simboli risolti staticamente e dinamicamente fino al tempo di collegamento statico per evitare il secondo.

L'altro problema riguarda i flag del compilatore. Questo problema esiste per qualsiasi programma composto da più unità di compilazione, le librerie dinamiche non devono essere coinvolte. Tuttavia è molto peggio su Windows. Su Unix non importa se si collega staticamente o dinamicamente, nessuno collega staticamente il runtime standard in ogni caso (in Linux potrebbe anche essere illegale) e non c'è un runtime di debug speciale, quindi una build è abbastanza buona. Ma il modo in cui Microsoft ha implementato il collegamento statico e dinamico, il debug e il runtime di rilascio e alcune altre opzioni significa che hanno causato l'esplosione combinatoria delle varianti di libreria necessarie. Di nuovo problema con la piattaforma piuttosto che con il linguaggio C ++.

    
risposta data 21.11.2012 - 15:52
fonte
7

No.

C'è un sacco di lavoro in corso per sostituire il sistema di intestazione, funzione chiamata Moduli e che potrebbe avere un impatto su questo, ma certamente non grande.

    
risposta data 21.11.2012 - 16:05
fonte

Leggi altre domande sui tag