Ao criar uma biblioteca de classes em C ++, você pode escolher entre bibliotecas dinâmicas ( .dll
, .so
) e estáticas ( .lib
, .a
). Qual é a diferença entre eles e quando é apropriado usar quais?
c++
dll
shared-libraries
static-linking
dynamic-linking
Morten Christiansen
fonte
fonte
Respostas:
Bibliotecas estáticas aumentam o tamanho do código no seu binário. Eles sempre são carregados e qualquer versão do código que você compilou é a versão do código que será executada.
Bibliotecas dinâmicas são armazenadas e versionadas separadamente. É possível que uma versão da biblioteca dinâmica seja carregada que não fosse a original que acompanha o seu código se a atualização for considerada binária compatível com a versão original.
Além disso, as bibliotecas dinâmicas não são necessariamente carregadas - geralmente são carregadas quando chamadas pela primeira vez - e podem ser compartilhadas entre componentes que usam a mesma biblioteca (vários carregamentos de dados, um carregamento de código).
As bibliotecas dinâmicas foram consideradas a melhor abordagem na maioria das vezes, mas originalmente elas tinham uma falha importante (inferno da DLL do Google), que foi praticamente eliminada pelos sistemas operacionais Windows mais recentes (Windows XP em particular).
fonte
Outros explicaram adequadamente o que é uma biblioteca estática, mas eu gostaria de destacar algumas das advertências sobre o uso de bibliotecas estáticas, pelo menos no Windows:
Singletons: se algo precisar ser global / estático e exclusivo, tenha muito cuidado em colocá-lo em uma biblioteca estática. Se várias DLLs estiverem vinculadas a essa biblioteca estática, cada uma receberá sua própria cópia do singleton. No entanto, se o seu aplicativo for um único EXE sem DLLs personalizadas, isso pode não ser um problema.
Remoção de código não referenciada: Quando você vincula uma biblioteca estática, apenas as partes da biblioteca estática referenciadas pela sua DLL / EXE são vinculadas à sua DLL / EXE.
Por exemplo, se
mylib.lib
contivera.obj
eb.obj
e seu DLL / EXE fizer referência apenas a funções ou variáveis dea.obj
, a totalidadeb.obj
será descartada pelo vinculador. Seb.obj
contiver objetos globais / estáticos, seus construtores e destruidores não serão executados. Se esses construtores / destruidores tiverem efeitos colaterais, você poderá se decepcionar com a ausência deles.Da mesma forma, se a biblioteca estática contiver pontos de entrada especiais, talvez seja necessário cuidar para que eles sejam realmente incluídos. Um exemplo disso na programação incorporada (ok, não no Windows) seria um manipulador de interrupções marcado como estando em um endereço específico. Você também precisa marcar o manipulador de interrupção como um ponto de entrada para garantir que ele não seja descartado.
Outra conseqüência disso é que uma biblioteca estática pode conter arquivos de objetos completamente inutilizáveis devido a referências não resolvidas, mas não causará um erro de vinculador até que você faça referência a uma função ou variável desses arquivos de objetos. Isso pode acontecer muito tempo após a biblioteca ser gravada.
Símbolos de depuração: você pode desejar um PDB separado para cada biblioteca estática ou os símbolos de depuração sejam colocados nos arquivos de objetos para que sejam inseridos no PDB para DLL / EXE. A documentação do Visual C ++ explica as opções necessárias .
RTTI: você pode acabar com vários
type_info
objetos da mesma classe se vincular uma única biblioteca estática em várias DLLs. Se o seu programa assume quetype_info
são dados "singleton" e usa&typeid()
ortype_info::before()
, você pode obter resultados indesejáveis e surpreendentes.fonte
Uma lib é uma unidade de código incluída no executável do aplicativo.
Uma dll é uma unidade autônoma de código executável. Ele é carregado no processo somente quando uma chamada é feita nesse código. Uma dll pode ser usada por vários aplicativos e carregada em vários processos, mantendo apenas uma cópia do código no disco rígido.
Dll profissionais : pode ser usado para reutilizar / compartilhar código entre vários produtos; carregar na memória do processo sob demanda e pode ser descarregado quando não for necessário; pode ser atualizado independentemente do restante do programa.
Contras da DLL : impacto no desempenho do carregamento da DLL e rebase do código; problemas de versão ("dll hell")
Prós da Lib : nenhum impacto no desempenho, pois o código é sempre carregado no processo e não é refeito; sem problemas de versão.
Contras da lib : executável / processo "inchar" - todo o código está no seu executável e é carregado no início do processo; sem reutilização / compartilhamento - cada produto possui sua própria cópia do código.
fonte
Além das implicações técnicas das bibliotecas estáticas e dinâmicas (os arquivos estáticos agrupam tudo em uma grande biblioteca binária versus dinâmica que permite o compartilhamento de código entre vários executáveis diferentes), existem as implicações legais .
Por exemplo, se você estiver usando o código licenciado pela LGPL e vincular estaticamente a uma biblioteca LGPL (e assim criar um binário grande), seu código se tornará automaticamente o código LGPL de código aberto ( livre como em liberdade) . Se você vincular a objetos compartilhados, precisará LGPL apenas das melhorias / correções feitas na própria biblioteca LGPL.
Isso se torna uma questão muito mais importante se você estiver decidindo como compilar seus aplicativos móveis, por exemplo (no Android, você pode escolher estático versus dinâmico, no iOS, não - é sempre estático).
fonte
Programas C ++ são criados em duas fases
A biblioteca estática (.lib) é apenas um pacote de arquivos .obj e, portanto, não é um programa completo. Não passou pela segunda fase (vinculação) da criação de um programa. DLLs, por outro lado, são como exe e, portanto, são programas completos.
Se você criar uma biblioteca estática, ela ainda não está vinculada e, portanto, os consumidores da sua biblioteca estática terão que usar o mesmo compilador que você usou (se você usou o g ++, eles terão que usar o g ++).
Se, em vez disso, você criou uma dll (e a criou corretamente ), criou um programa completo que todos os consumidores podem usar, independentemente do compilador que estiverem usando. Porém, existem várias restrições na exportação de uma dll, se a compatibilidade entre compiladores for desejada.
fonte
consumers of your static library will have to use the same compiler that you used
se a biblioteca estática usa a biblioteca C ++, como#include <iostream>
.Criando uma biblioteca estática
criando uma biblioteca dinâmica
fonte
Uma biblioteca estática é compilada no cliente. Um .lib é usado em tempo de compilação e o conteúdo da biblioteca se torna parte do executável consumidor.
Uma biblioteca dinâmica é carregada em tempo de execução e não compilada no executável do cliente. As bibliotecas dinâmicas são mais flexíveis, pois vários executáveis de clientes podem carregar uma DLL e utilizar sua funcionalidade. Isso também mantém o tamanho geral e a capacidade de manutenção do código do cliente em um nível mínimo.
fonte
Você deve pensar cuidadosamente sobre alterações ao longo do tempo, controle de versão, estabilidade, compatibilidade etc.
Se houver dois aplicativos que usam o código compartilhado, você deseja forçá-los a mudar juntos, caso precisem ser compatíveis entre si? Em seguida, use a dll. Todos os exe estarão usando o mesmo código.
Ou você deseja isolá-los um do outro, para poder mudar um e ter certeza de que não quebrou o outro. Em seguida, use a lib estática.
O inferno da DLL é quando você provavelmente DEVERIA ter usado uma lib estática, mas em vez disso uma dll, e nem todos os exes são em coma com ela.
fonte
Uma biblioteca estática deve ser vinculada ao executável final; torna-se parte do executável e segue-o onde quer que vá. Uma biblioteca dinâmica é carregada toda vez que o executável é executado e permanece separado do executável como um arquivo DLL.
Você usaria uma DLL quando quiser alterar a funcionalidade fornecida pela biblioteca sem precisar vincular novamente o executável (basta substituir o arquivo DLL, sem precisar substituir o arquivo executável).
Você usaria uma biblioteca estática sempre que não tiver um motivo para usar uma biblioteca dinâmica.
fonte
O artigo de Ulrich Drepper sobre " Como escrever bibliotecas compartilhadas " também é um bom recurso que detalha a melhor forma de aproveitar as bibliotecas compartilhadas, ou o que ele chama de "Objetos Compartilhados Dinâmicos" (DSOs). Ele se concentra mais em bibliotecas compartilhadas no formato binário ELF , mas algumas discussões também são adequadas para DLLs do Windows.
fonte
Para uma excelente discussão sobre este tópico, leia este artigo da Sun.
Ele inclui todos os benefícios, incluindo a possibilidade de inserir bibliotecas interpostas. Mais detalhes sobre a interposição podem ser encontrados neste artigo aqui .
fonte
Realmente a troca que você está fazendo (em um projeto grande) está no tempo de carregamento inicial, as bibliotecas serão vinculadas uma vez ou outra, a decisão que precisa ser tomada é que o link levará tempo suficiente para que o compilador precise morder a bala e fazê-lo com antecedência, ou o vinculador dinâmico pode fazê-lo no tempo de carregamento.
fonte
Se sua biblioteca for compartilhada entre vários executáveis, geralmente faz sentido dinamizar a redução do tamanho dos executáveis. Caso contrário, definitivamente torne-o estático.
Existem várias desvantagens de usar uma dll. Existe uma sobrecarga adicional para carregá-lo e descarregá-lo. Há também uma dependência adicional. Se você alterar a dll para torná-la incompatível com a sua execução, eles deixarão de funcionar. Por outro lado, se você alterar uma biblioteca estática, seus executáveis compilados usando a versão antiga não serão afetados.
fonte
Se a biblioteca for estática, no momento do link, o código será vinculado ao seu executável. Isso torna seu executável maior (do que se você seguisse a rota dinâmica).
Se a biblioteca for dinâmica, no momento do link, as referências aos métodos necessários serão incorporadas ao seu executável. Isso significa que você precisa enviar seu executável e a biblioteca dinâmica. Você também deve considerar se o acesso compartilhado ao código na biblioteca é seguro, endereço de carregamento preferido entre outras coisas.
Se você pode viver com a biblioteca estática, vá com a biblioteca estática.
fonte
Usamos muitas DLLs (> 100) em nosso projeto. Essas DLLs têm dependências entre si e, portanto, escolhemos a configuração do vínculo dinâmico. No entanto, possui as seguintes desvantagens:
Talvez uma configuração melhor fosse tornar tudo uma biblioteca estática (e, portanto, você só tem um executável). Isso funciona apenas se nenhuma duplicação de código ocorrer. Um teste parece apoiar essa suposição, mas não consegui encontrar uma cotação oficial do MSDN. Então, por exemplo, faça 1 exe com:
O código e as variáveis de shared_lib2 devem estar presentes no executável mesclado final apenas uma vez. Alguém pode apoiar esta pergunta?
fonte
Bibliotecas estáticas são arquivos que contêm o código de objeto da biblioteca, quando vinculados a um aplicativo em que o código é compilado no executável. As bibliotecas compartilhadas são diferentes, pois não são compiladas no executável. Em vez disso, o vinculador dinâmico procura em alguns diretórios procurando a (s) biblioteca (s) necessária (s) e carrega-o na memória. Mais do que um executável pode usar a mesma biblioteca compartilhada ao mesmo tempo, reduzindo assim o uso de memória e o tamanho do executável. No entanto, existem mais arquivos para distribuir com o executável. Você precisa garantir que a biblioteca esteja instalada no sistema de usos em algum lugar onde o vinculador possa encontrá-la. A vinculação estática elimina esse problema, mas resulta em um arquivo executável maior.
fonte
Se você trabalha em projetos incorporados ou em bibliotecas estáticas de plataformas especializadas, é o único caminho a percorrer, também muitas vezes são menos complicadas de serem compiladas em seu aplicativo. Também ter projetos e arquivos que incluam tudo torna a vida mais feliz.
fonte
Eu daria uma regra geral de que, se você tiver uma grande base de código, toda construída em bibliotecas de nível inferior (por exemplo, uma estrutura Utils ou Gui), que você deseja particionar em bibliotecas mais gerenciáveis, então as tornará bibliotecas estáticas. As bibliotecas dinâmicas não compram nada para você e há menos surpresas - haverá apenas uma instância de singletons, por exemplo.
Se você possui uma biblioteca totalmente separada do restante da base de código (por exemplo, uma biblioteca de terceiros), considere torná-la uma dll. Se a biblioteca for LGPL, você poderá precisar usar uma DLL de qualquer maneira, devido às condições de licenciamento.
fonte