Статическое или динамическое связывание CRT, MFC, ATL и т. Д.

Еще в 90-х, когда я только начинал работать с MFC, я использовал для динамического связывания своих приложений и отправлял соответствующие библиотеки DLL MFC. Это вызвало у меня несколько проблем (ад DLL!), И вместо этого я переключился на статическое связывание - не только для MFC, но и для CRT и ATL. За исключением более крупных EXE-файлов, статическая компоновка никогда не вызывала у меня никаких проблем - так есть ли какие-то недостатки, с которыми сталкивались другие люди? Есть ли веская причина снова вернуться к динамическому связыванию? Мои приложения - это в основном STL / Boost, в настоящее время FWIW.


person Rob    schedule 26.10.2008    source источник


Ответы (7)


Есть и минусы:

  • Больший размер exe (особенно, если вы отправляете несколько exe)
  • Проблемы с использованием других DLL, которые полагаются или предполагают динамическое связывание (например, сторонние DLL, которые вы не можете получить как статические библиотеки)
  • Различные c-среды выполнения между DLL с независимой статической связью (без распределения / освобождения кросс-модуля)
  • Отсутствие автоматического обслуживания общих компонентов (отсутствие возможности обновления кода стороннего поставщика модулей для устранения проблем без перекомпиляции и обновления вашего приложения)

Мы выполняем статическое связывание для наших приложений Windows, в первую очередь потому, что оно позволяет развертывать xcopy, что просто невозможно при установке или использовании SxS DLL таким образом, который работает, поскольку процесс и механизм плохо документированы или легко переносятся. Если вы используете локальные библиотеки DLL в каталоге установки, это вроде как работает, но не поддерживается. Невозможность легко выполнить удаленную установку без использования MSI в удаленной системе является основной причиной, по которой мы не используем динамическое связывание, но (как вы указали) статическое связывание дает много других преимуществ. У каждого есть свои плюсы и минусы; надеюсь, это поможет их перечислить.

person Nick    schedule 27.10.2008
comment
Возможно, лучший подход (частные сборки) описан в stackoverflow.com/questions/787216 - person Weidenrinde; 13.05.2009

Большинство ответов, которые я слышу об этом, связаны с совместным использованием вашей библиотеки DLL с другими программами или с обновлением этих DLL без необходимости исправлять ваше программное обеспечение.

Честно говоря, я считаю это недостатками, а не достоинствами. Когда обновляется сторонняя DLL, она может измениться достаточно, чтобы сломать ваше программное обеспечение. И в наши дни место на жестком диске не так ценно, как раньше, лишние 500 КБ в вашем исполняемом файле? Какая разница?

  • Быть на 100% уверенным в версии dll, которую использует ваше программное обеспечение, - это хорошо.
  • Быть на 100% уверенным, что у клиента не будет головной боли, связанной с зависимостями, - это хорошо.

На мой взгляд, плюсы перевешивают минусы

person Kevin Laity    schedule 16.01.2009

Пока вы ограничиваете свое использование определенными библиотеками и не используете какие-либо библиотеки DLL, у вас все должно быть хорошо.

К сожалению, есть библиотеки, которые нельзя связать статически. Лучший пример, который у меня есть, - OpenMP. Если вы воспользуетесь преимуществами поддержки OpenMP в Visual Studio, вам нужно будет убедиться, что среда выполнения установлена ​​(в данном случае vcomp.dll).

Если вы действительно используете dll, вы не сможете передавать некоторые предметы туда и обратно без серьезной гимнастики. На ум приходят std :: strings. Если ваш exe и dll динамически связаны, то распределение происходит в CRT. В противном случае ваша программа может попытаться выделить строку с одной стороны и освободить ее с другой. За этим следуют плохие вещи ...

Тем не менее, я все еще статически связываю свои exe и dll. Это значительно снижает вариативность при установке, и я считаю, что это стоит некоторых ограничений.

person Jere.Jones    schedule 26.10.2008
comment
Дело в том, что распределение памяти неверно. Когда вы используете DLL CRT, в приложении присутствует только одна CRT, поэтому вы можете выделить из одной DLL и освободить в другой, все это попадает в одну и ту же кучу, поскольку это одна и та же CRT. - person Adam Mitz; 27.10.2008
comment
Верно, но если exe и dll статически связаны, то есть две кучи. Правильно? По крайней мере, таков мой опыт. Я должен сказать тебе, что возможность передавать std :: string вперед и назад или вектор сделало бы мою жизнь намного проще. - person Jere.Jones; 28.10.2008
comment
Решение проблемы std :: string - это не пустяки. Либо связывайте статически, либо связывайте динамически. Если у вас есть хотя бы одна C ++ DLL, сделайте ссылку на CRT DLL. - person MSalters; 19.01.2009

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

person Laserallan    schedule 26.10.2008
comment
Это может сэкономить системную память за счет дедупликации страниц, но фактически сокращается виртуальное адресное пространство отдельного процесса - вместо только части библиотеки, втянутой в исполняемый файл, у вас есть вся библиотека, отображаемая в адресное пространство процесса. При отображении нескольких библиотек DLL и ASLR виртуальное адресное пространство процесса фрагментируется, что по крайней мере для 32-разрядных приложений значительно уменьшает размер непрерывного блока памяти, который может быть выделен. - person Igor Levicki; 27.06.2013

Нет, ничего нового в этом направлении. Продолжай в том-же духе.

person Serge Wautier    schedule 26.10.2008

Определенно.

Распределение выполняется в «статической» куче. Поскольку выделение и освобождение должно выполняться в той же куче, это означает, что если вы отправляете библиотеку, вы должны позаботиться о том, чтобы клиентский код не мог вызвать «ваш» p = new LibClass() и удалить сам этот объект с помощью delete p;.

Мой вывод: либо экранировать выделение и освобождение от клиентского кода, либо динамически связывать CRT.

person xtofl    schedule 26.10.2008

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

person Mark Ransom    schedule 26.02.2010
comment
Если у вас есть для использования такой библиотеки, вы можете заплатить выкуп за статическую ссылку (вместо того, чтобы таскать с собой DLL). - person Navin; 10.04.2014