Когда использовать динамические и статические библиотеки - PullRequest
413 голосов
/ 26 сентября 2008

При создании библиотеки классов в C ++ вы можете выбирать между динамическими (.dll, .so) и статическими (.lib, .a) библиотеками. В чем разница между ними и когда уместно использовать какие?

Ответы [ 18 ]

283 голосов
/ 26 сентября 2008

Статические библиотеки увеличивают размер кода в вашем двоичном файле. Они всегда загружаются, и любая версия кода, с которой вы скомпилировали, является версией кода, который будет выполняться.

Динамические библиотеки хранятся и версии отдельно. Возможно загрузить версию динамической библиотеки, отличную от оригинальной, которая поставляется с вашим кодом , если обновление считается двоичным, совместимым с исходной версией.

Кроме того, динамические библиотеки не обязательно загружаются - они обычно загружаются при первом вызове - и могут использоваться совместно компонентами, использующими одну и ту же библиотеку (несколько загрузок данных, одна загрузка кода).

Динамические библиотеки считались лучшим подходом в большинстве случаев, но изначально у них был серьезный недостаток (ад Google gll DLL), который практически исключен более поздними версиями ОС Windows (в частности, Windows XP).

183 голосов
/ 26 сентября 2008

Другие адекватно объяснили, что такое статическая библиотека, но я хотел бы указать на некоторые предостережения об использовании статических библиотек, по крайней мере, в Windows:

  • Одиночные: Если что-то должно быть глобальным / статическим и уникальным, будьте очень осторожны при помещении его в статическую библиотеку. Если несколько статических библиотек связаны с этой статической библиотекой, каждая из них получит свою собственную копию синглтона. Однако, если ваше приложение представляет собой один EXE-файл без пользовательских DLL, это может не быть проблемой.

  • Удаление кода без ссылок: Когда вы ссылаетесь на статическую библиотеку, в вашу DLL / EXE будут связаны только те части статической библиотеки, на которые ссылается ваша DLL / EXE.

    Например, если mylib.lib содержит a.obj и b.obj и ваша DLL / EXE ссылается только на функции или переменные из a.obj, компоновщик полностью отбрасывает b.obj. Если b.obj содержит глобальные / статические объекты, их конструкторы и деструкторы не будут выполнены. Если у этих конструкторов / деструкторов есть побочные эффекты, вы можете быть разочарованы их отсутствием.

    Аналогичным образом, если статическая библиотека содержит специальные точки входа, вам, возможно, потребуется позаботиться о том, чтобы они действительно были включены. Примером этого во встроенном программировании (хорошо, не в Windows) будет обработчик прерываний, который помечен как определенный адрес. Вам также нужно пометить обработчик прерываний как точку входа, чтобы убедиться, что он не сбрасывается.

    Еще одним следствием этого является то, что статическая библиотека может содержать объектные файлы, которые полностью непригодны для использования из-за неразрешенных ссылок, но это не вызовет ошибку компоновщика, пока вы не обратитесь к функции или переменной из этих объектных файлов. Это может произойти спустя много времени после написания библиотеки.

  • Символы отладки: Вы можете захотеть отдельную PDB для каждой статической библиотеки, или вы можете захотеть, чтобы символы отладки были помещены в объектные файлы, чтобы они были свернуты в PDB для DLL / EXE. Документация по Visual C ++ объясняет необходимые опции .

  • RTTI: Вы можете получить несколько type_info объектов для одного и того же класса, если объедините одну статическую библиотеку в несколько библиотек DLL. Если ваша программа предполагает, что type_info является «одноэлементными» данными и использует &typeid() или type_info::before(), вы можете получить нежелательные и неожиданные результаты.

59 голосов
/ 26 сентября 2008

Библиотека - это единица кода, включенная в исполняемый файл вашего приложения.

DLL - это автономная единица исполняемого кода. Он загружается в процессе только тогда, когда вызов сделан в этот код. DLL может использоваться несколькими приложениями и загружаться в несколько процессов, при этом на жестком диске остается только одна копия кода.

Dll профи : может использоваться для повторного использования / обмена кодом между несколькими продуктами; загружать в память процесса по требованию и может быть выгружен при необходимости; может быть обновлен независимо от остальной части программы.

Dll минусы : влияние на производительность загрузки DLL и перебазирование кода; проблемы с версиями ("dll hell")

Lib pros : не влияет на производительность, так как код всегда загружается в процессе и не перебазируется; нет проблем с версиями.

Lib cons : исполняемый файл / процесс "раздут" - весь код находится в вашем исполняемом файле и загружается при запуске процесса; нет повторного использования / совместного использования - каждый продукт имеет свою собственную копию кода.

21 голосов
/ 16 октября 2009

Помимо технических последствий использования статических и динамических библиотек (статические файлы объединяют все в один большой двоичный файл и динамические библиотеки, которые обеспечивают совместное использование кода несколькими различными исполняемыми файлами), существуют юридические последствия .

Например, если вы используете лицензионный код LGPL и статически связываетесь с библиотекой LGPL (и, следовательно, создаете один большой двоичный файл), ваш код автоматически становится открытым исходным кодом ( бесплатно как при свободе) код LGPL , Если вы ссылаетесь на общие объекты, то вам нужно только LGPL улучшить / исправить ошибки, которые вы вносите в саму библиотеку LGPL.

Это становится гораздо более важной проблемой, если вы решаете, например, как скомпилировать ваши мобильные приложения (в Android у вас есть выбор между статическим и динамическим, в iOS нет - всегда статичным).

18 голосов
/ 14 декабря 2009

Создание статической библиотеки

$$:~/static [32]> cat foo.c
#include<stdio.h>
void foo()
{
printf("\nhello world\n");
}
$$:~/static [33]> cat foo.h
#ifndef _H_FOO_H
#define _H_FOO_H

void foo();

#endif
$$:~/static [34]> cat foo2.c
#include<stdio.h>
void foo2()
{
printf("\nworld\n");
}
$$:~/static [35]> cat foo2.h
#ifndef _H_FOO2_H
#define _H_FOO2_H

void foo2();

#endif
$$:~/static [36]> cat hello.c
#include<foo.h>
#include<foo2.h>
void main()
{
foo();
foo2();
}
$$:~/static [37]> cat makefile
hello: hello.o libtest.a
        cc -o hello hello.o -L. -ltest
hello.o: hello.c
        cc -c hello.c -I`pwd`
libtest.a:foo.o foo2.o
        ar cr libtest.a foo.o foo2.o
foo.o:foo.c
        cc -c foo.c
foo2.o:foo.c
        cc -c foo2.c
clean:
        rm -f foo.o foo2.o libtest.a hello.o

$$:~/static [38]>

создание динамической библиотеки

$$:~/dynamic [44]> cat foo.c
#include<stdio.h>
void foo()
{
printf("\nhello world\n");
}
$$:~/dynamic [45]> cat foo.h
#ifndef _H_FOO_H
#define _H_FOO_H

void foo();

#endif
$$:~/dynamic [46]> cat foo2.c
#include<stdio.h>
void foo2()
{
printf("\nworld\n");
}
$$:~/dynamic [47]> cat foo2.h
#ifndef _H_FOO2_H
#define _H_FOO2_H

void foo2();

#endif
$$:~/dynamic [48]> cat hello.c
#include<foo.h>
#include<foo2.h>
void main()
{
foo();
foo2();
}
$$:~/dynamic [49]> cat makefile
hello:hello.o libtest.sl
        cc -o hello hello.o -L`pwd` -ltest
hello.o:
        cc -c -b hello.c -I`pwd`
libtest.sl:foo.o foo2.o
        cc -G -b -o libtest.sl foo.o foo2.o
foo.o:foo.c
        cc -c -b foo.c
foo2.o:foo.c
        cc -c -b foo2.c
clean:
        rm -f libtest.sl foo.o foo

2.o hello.o
$$:~/dynamic [50]>
17 голосов
/ 08 августа 2014

C ++ программы строятся в два этапа

  1. Компиляция - создает объектный код (.obj)
  2. Linking - создает исполняемый код (.exe или .dll)

Статическая библиотека (.lib) - это просто набор файлов .obj и, следовательно, не полная программа. Он не прошел второй (связующий) этап построения программы. Dll, с другой стороны, похожи на exe и поэтому являются законченными программами.

Если вы создаете статическую библиотеку, она еще не связана, и поэтому потребители вашей статической библиотеки должны будут использовать тот же компилятор, который вы использовали (если вы использовали g ++, они должны будут использовать g ++).

Если вместо этого вы собрали dll (и правильно его построили ), вы создали полную программу, которую могут использовать все потребители, независимо от того, какой компилятор они используют. Однако существует несколько ограничений на экспорт из DLL, если требуется кросс-компиляторная совместимость.

12 голосов
/ 26 сентября 2008

Тщательно продумайте изменения во времени, версии, стабильность, совместимость и т. Д.

Если есть два приложения, которые используют общий код, хотите ли вы заставить эти приложения изменяться вместе, если они должны быть совместимы друг с другом? Тогда используйте DLL. Все исполняемые файлы будут использовать один и тот же код.

Или вы хотите изолировать их друг от друга, чтобы вы могли изменить один и быть уверенным, что не сломали другой. Затем используйте статическую библиотеку.

DLL, черт возьми, это когда вы, вероятно, ДОЛЖНЫ использовать статическую библиотеку, но вместо этого вы использовали dll, и не все exes совместимы с ней.

11 голосов
/ 26 сентября 2008

Статическая библиотека компилируется в клиент. .Lib используется во время компиляции, а содержимое библиотеки становится частью исполняемого файла-потребителя.

Динамическая библиотека загружается во время выполнения и не компилируется в исполняемый файл клиента. Динамические библиотеки более гибкие, так как несколько клиентских исполняемых файлов могут загружать DLL и использовать ее функциональные возможности. Это также сводит к минимуму общий размер и удобство обслуживания вашего клиентского кода.

9 голосов
/ 26 сентября 2008

Статическая библиотека должна быть связана с конечным исполняемым файлом; он становится частью исполняемого файла и следует за ним куда угодно. Динамическая библиотека загружается при каждом выполнении исполняемого файла и остается отдельной от исполняемого файла в виде файла DLL.

Вы можете использовать DLL, если хотите иметь возможность изменять функциональные возможности, предоставляемые библиотекой, без необходимости повторного связывания исполняемого файла (просто замените файл DLL, не заменяя исполняемый файл).

Вы будете использовать статическую библиотеку, когда у вас нет причин использовать динамическую библиотеку.

7 голосов
/ 12 мая 2009

Статья Ульриха Дреппера на тему " Как писать общие библиотеки " также является хорошим ресурсом, в котором подробно рассказывается о том, как наилучшим образом использовать преимущества общих библиотек, или о том, что он называет "динамическими общими объектами" (DSO). В нем больше внимания уделяется общим библиотекам в двоичном формате ELF , но некоторые обсуждения также подходят для библиотек DLL Windows.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...