Статическое или динамическое связывание CRT, MFC, ATL и т. Д.
Еще в 90-х годах, когда я только начал работать с MFC, я использовал для динамического связывания своих приложений и отправлял соответствующие библиотеки MFC. Это вызвало у меня несколько проблем (DLL, черт возьми!), И я вместо этого переключился на статическое связывание - не только для MFC, но и для CRT и ATL. Кроме больших EXE-файлов, статические ссылки никогда не вызывали у меня никаких проблем - есть ли минусы, с которыми сталкивались другие люди? Есть ли веская причина для повторного пересмотра динамических ссылок? Мои приложения в основном STL/Boost в настоящее время FWIW.
7 ответов
Есть некоторые недостатки:
- Больший размер exe (особенно если вы отправляете несколько exe)
- Проблемы с использованием других библиотек DLL, которые полагаются или предполагают динамическое связывание (например, библиотеки сторонних производителей, которые вы не можете получить в качестве статических библиотек)
- Различные c-runtime между DLL-библиотеками с независимой статической связью (без межмодульного размещения / освобождения)
- Отсутствует автоматическое обслуживание общих компонентов (нет возможности заставить сторонний поставщик модулей обновлять свой код для устранения проблем без перекомпиляции и обновления приложения)
Мы делаем статическое связывание для наших приложений Windows, в первую очередь потому, что оно позволяет развертывание xcopy, что просто невозможно при установке или использовании библиотек DLL SxS таким способом, который работает, поскольку процесс и механизм плохо документированы или не могут быть легко удалены. Если вы используете локальные библиотеки DLL в каталоге установки, это будет работать, но не очень хорошо поддерживается. Неспособность легко выполнить удаленную установку без прохождения MSI в удаленной системе является основной причиной, по которой мы не используем динамическое связывание, но (как вы указали) есть много других преимуществ для статического связывания. Есть плюсы и минусы для каждого; надеюсь, это поможет перечислить их.
Большинство ответов, которые я слышу об этом, включают в себя совместное использование ваших dll с другими программами или обновление этих dll без необходимости исправления вашего программного обеспечения.
Честно говоря, я считаю, что это минусы, а не минусы. Когда сторонний dll обновлен, он может измениться достаточно, чтобы сломать ваше программное обеспечение. И в наши дни, место на жестком диске не так ценно, как это было раньше, дополнительные 500 КБ в вашем исполняемом файле? Какая разница?
- Быть на 100% уверенным в версии dll, которую использует ваше программное обеспечение - это хорошо.
- Быть на 100% уверенным, что у клиента не будет головной боли от зависимостей - это хорошо.
Недостатки намного перевешивают недостатки на мой взгляд
Пока вы ограничиваете использование определенных библиотек и не используете никакие библиотеки DLL, тогда все будет хорошо.
К сожалению, есть некоторые библиотеки, которые вы не можете связать статически. Лучший пример, который у меня есть, - OpenMP. Если вы используете поддержку OpenMP в Visual Studio, вы должны убедиться, что установлена среда выполнения (в данном случае vcomp.dll).
Если вы используете DLL, то вы не можете передавать некоторые предметы туда-сюда без серьезной гимнастики. Std:: Strings приходят на ум. Если ваши exe и dll динамически связаны, то распределение происходит в CRT. В противном случае ваша программа может попытаться выделить строку с одной стороны и освободить ее с другой. Плохие вещи...
Тем не менее, я все еще статически связываю свои exe и dll's. Это значительно снижает вариативность в установке, и я считаю, что это стоит тех немногих ограничений.
Хорошей особенностью использования DLL является то, что если несколько процессоров загружают одну и ту же DLL, ее код может быть разделен между ними. Это может сэкономить память и сократить время загрузки приложения, загружающего DLL, которая уже используется другой программой.
Существуют некоторые лицензии на программное обеспечение, такие как LGPL, которые требуют от вас использования DLL или распространения приложения в виде объектных файлов, которые пользователь может связать вместе. Если вы используете такую библиотеку, вы, вероятно, захотите использовать ее в качестве библиотеки DLL.
Вероятнее всего.
Распределение выполняется в "статической" куче. Поскольку распределение освобождение должно выполняться в одной и той же куче, это означает, что если вы отправляете библиотеку, вы должны позаботиться о том, чтобы код клиента не мог вызывать "ваш" p = new LibClass()
и удалить этот объект сам, используя delete p;
,
Мой вывод: либо защитить выделение и освобождение от клиентского кода, либо динамически связать CRT.