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