Uma das minhas principais reclamações sobre C ++ é a dificuldade na prática de passar objetos de biblioteca std fora dos limites da biblioteca dinâmica (por exemplo, dll / so).
A biblioteca std geralmente é apenas de cabeçalho. O que é ótimo para fazer algumas otimizações incríveis. No entanto, para as DLLs, elas geralmente são criadas com configurações diferentes do compilador que podem impactar a estrutura / código interno dos contêineres de uma biblioteca std. Por exemplo, no MSVC, uma dll pode criar com a depuração do iterador ativada, enquanto outra cria com a desativação. Essas duas DLLs podem ter problemas ao passar contêineres std. Se eu expor std::string
na minha interface, não posso garantir que o código que o cliente está usando std::string
seja uma correspondência exata da minha biblioteca std::string
.
Isso leva a problemas difíceis de depurar, dores de cabeça etc. Você controla rigidamente as configurações do compilador em sua organização para evitar esses problemas ou usa uma interface C mais simples que não terá esses problemas. Ou especifique para seus clientes as configurações esperadas do compilador que eles devem usar (o que é ruim se outra biblioteca especificar outras configurações do compilador).
Minha pergunta é se o C ++ 11 tentou ou não fazer alguma coisa para resolver esses problemas?
DLL
s. EntreSO
s sempre funcionou muito bem.Respostas:
Você está certo de que qualquer coisa STL - na verdade, qualquer coisa de qualquer biblioteca de terceiros modelada - é melhor evitar em qualquer API pública do C ++. Você também deseja seguir a longa lista de regras em http://www.ros.org/reps/rep-0009.html#definition para inibir a quebra da ABI, o que torna a programação das APIs públicas do C ++ uma tarefa árdua.
E a resposta em relação ao C ++ 11 é não, esse padrão não está afetando isso. Mais interessante é por que não? A resposta é que o C ++ 17 é muito comovente e, para que os módulos C ++ sejam implementados, precisamos de modelos exportados para funcionar, e para isso precisamos de um compilador do tipo LLVM, como o clang, que pode despejar o AST completo no disco e depois faça pesquisas dependentes de chamador para lidar com os muitos casos de violação de ODR em qualquer projeto grande de C ++ - que, a propósito, inclui muitos códigos GCC e ELF.
Por fim, vejo muitos comentários de ódio e pró-CCG da MSVC. Eles são muito mal informados - o GCC no ELF é fundamental e irremediavelmente incapaz de produzir código C ++ válido e correto. Os motivos para isso são muitos e muitos, mas citarei rapidamente um exemplo de caso: o GCC no ELF não pode produzir com segurança extensões do Python escritas usando o Boost.Python, onde mais de uma extensão baseada no Boost.Python é carregada no Python. Isso porque o ELF com sua tabela de símbolos C global é simplesmente incapaz de impedir violações de ODR que causam segfaults, enquanto PE e MachO e, de fato, a especificação proposta dos Módulos C ++ usam tabelas de símbolos por módulo - o que, aliás, também significa tempos de inicialização do processo muito mais rápidos. E há muitos outros problemas: consulte um StackOverflow que respondi recentemente emhttps://stackoverflow.com/questions/14268736/symbol-visibility-exceptions-runtime-error/14364055#14364055 por exemplo, onde lançamentos de exceção do C ++ são irremediavelmente fundamentalmente interrompidos no ELF.
Último ponto: em relação à interoperabilidade de diferentes STLs, isso é um grande problema para muitos usuários corporativos grandes que tentam misturar bibliotecas de terceiros fortemente integradas a alguma implementação de STL. A única solução é um novo mecanismo para o C ++ lidar com a interoperabilidade STL, e enquanto estiver nisso, você também poderá corrigir a interoperabilidade do compilador para que você possa (por exemplo) misturar arquivos de objetos compilados MSVC, GCC e clang e tudo funcione . Eu assistia ao esforço do C ++ 17 e veria o que acontece lá nos próximos anos - ficaria surpreso se nada acontecer.
fonte
A especificação nunca teve esse problema. Isso ocorre porque ele possui um conceito chamado "regra de uma definição", que exige que cada símbolo tenha exatamente uma definição no processo em execução.
As DLLs do Windows violam esse requisito. É por isso que existem todos esses problemas. Portanto, é responsabilidade da Microsoft corrigi-lo, não do comitê de padronização do C ++. O Unix nunca teve esse problema, porque as bibliotecas compartilhadas funcionam de maneira diferente lá e, por padrão, estão em conformidade com uma regra de definição (você pode explicitamente quebrá-la, mas obviamente só o faz se souber que pode pagar e precisa extrair os poucos ciclos extras).
As DLLs do Windows violam uma regra de definição porque:
O Unix usando exportações de formato ELF importa implicitamente todos os símbolos exportados para evitar o primeiro problema e não distingue entre símbolos resolvidos estaticamente e dinamicamente até o tempo de link estático para evitar o segundo.
O outro problema é de sinalizadores do compilador. Esse problema existe para qualquer programa composto de várias unidades de compilação; as bibliotecas dinâmicas não precisam estar envolvidas. No entanto, é muito pior no Windows. No Unix, não importa realmente se você vincula estaticamente ou dinamicamente, ninguém vincula estaticamente o tempo de execução padrão de qualquer maneira (no Linux pode até ser ilegal) e não há nenhum tempo de execução de depuração especial, portanto, uma compilação é boa o suficiente. Mas a maneira como a Microsoft implementou a vinculação estática e dinâmica, o tempo de execução de depuração e liberação e algumas outras opções significa que eles causaram a explosão combinatória das variantes necessárias da biblioteca. Novamente problema de plataforma em vez de problema de linguagem C ++.
fonte
Não.
Há muito trabalho em andamento para substituir o sistema de cabeçalho, recurso chamado Módulos e que pode ter um impacto nisso, mas certamente não é grande.
fonte