Что нужно для компиляции с / MD или / MT?

127

В Visual Studio есть флаги компиляции / MD и / MT, которые позволяют вам выбрать, какой тип библиотеки времени выполнения C.

Я понимаю разницу в реализации, но все еще не уверен, какую из них использовать. Какие плюсы / минусы?

Одно из преимуществ / MD, о котором я слышал, заключается в том, что это позволяет кому-то обновлять среду выполнения (например, исправлять проблему безопасности), и мое приложение получит выгоду от этого обновления. Хотя для меня это почти не похоже на функцию: я не хочу, чтобы люди меняли мою среду выполнения, не позволяя мне протестировать новую версию!

Некоторые вещи, которые мне любопытны:

  • Как это повлияет на время сборки? (предположительно / MT немного медленнее?)
  • Какие еще последствия?
  • Какой из них использует большинство людей?
Энди
источник
1
Дополнительную информацию и предложения можно найти в: stackoverflow.com/questions/787216
Weidenrinde

Ответы:

87

Динамически связываясь с / MD,

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

Я также обнаружил, что на практике при работе со статически связанными сторонними библиотеками, предназначенными только для двоичных файлов, которые были созданы с разными параметрами времени выполнения, / MT в основном приложении имеет тенденцию вызывать конфликты гораздо чаще, чем / MD (потому что вы возникнут проблемы, если среда выполнения C будет статически связана несколько раз, особенно если это разные версии).

Г-н Фуз
источник
11
Бит обновления системы несколько уменьшен SxS. EXE должен объявить, какую версию CRT он хочет (хочет, а не получает - обновления безопасности могут отменить это)
MSalters
1
Означает ли это, что если я компилирую с использованием MD, а моя программа зависит от некоторой dll, программа выйдет из строя, если она запущена на компьютере, на котором не существует зависимой dll?
gerrytan 03
5
@gerrytan: Да, вам необходимо убедиться, что соответствующие используемые библиотеки DLL присутствуют на всех компьютерах, на которых нужно запускать программное обеспечение. Типичные решения этой проблемы заключаются в том, чтобы пользователь установил соответствующий распространяемый пакет MSVC или использовал установщик, который выполняет всю работу.
Мистер Фуз
@Royi Я не уверен, но я думаю /MT, что во время выполнения будет немного быстрее, поскольку вашему приложению не нужно каждый раз искать реализацию функции времени выполнения, я не эксперт на этом уровне, но я почти уверен, что большая часть ОС будут кэшировать реализации среды выполнения, поэтому ваше приложение будет использовать кешированную версию, поэтому разница будет не такой уж большой. ПРИМЕЧАНИЕ. Я упомянул, что не уверен, поэтому не принимайте этот комментарий в качестве аргумента.
Ахмед Камаль
34

Если вы используете библиотеки DLL, вам следует выбрать динамически подключаемый CRT (/ MD).

Если вы используете динамический CRT для своего .exe и всех .dll, тогда все они будут использовать одну реализацию CRT - это означает, что все они будут совместно использовать одну кучу CRT, а память, выделенная в одном .exe / .dll, может быть освобождена в другой.

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

JoeG
источник
20

Я считаю, что по умолчанию для проектов, созданных с помощью Visual Studio, / MD.

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

Я сам использую / MT, так что могу игнорировать весь беспорядок DLL.

PS Как отмечает г-н Фуз , очень важно быть последовательным. Если вы связываетесь с другими библиотеками, вам нужно использовать ту же опцию, что и они. Если вы используете стороннюю DLL, почти наверняка вам понадобится DLL-версия библиотеки времени выполнения.

Марк Рэнсом
источник
14

Я предпочитаю связывать статически с / MT.

Несмотря на то, что вы получаете исполняемый файл меньшего размера с / MD, вам все равно придется отправить кучу DLL, чтобы убедиться, что пользователь получает правильную версию для запуска вашей программы. И, в конце концов, ваш установщик будет БОЛЬШЕ, чем при связывании с / MT.

Что еще хуже, если вы решите поместить свои библиотеки времени выполнения в каталог Windows, рано или поздно пользователь установит новое приложение с другими библиотеками и, если не повезет, сломает ваше приложение.

Адриан Григоре
источник
5
Очень плохая идея «поместить ваши библиотеки времени выполнения в каталог Windows». Вы можете сломать другие глупые приложения, которые делали то же самое до вас. Используйте SxS и позвольте установщику обработать это, или придерживайтесь / MT.
MSalters
1
Я полностью согласен, что это плохая идея. Однако некоторые люди так поступают, поэтому я объяснил, почему это не очень хорошая идея.
Адриан Григоре
@AdrianGrigore, почему новое приложение с другими библиотеками может вызвать сбой в вашем приложении? Если вы используете связь / MD, вы бы просто начали загружать новые версии библиотек, верно?
rturrado
4
@rturrado: не совсем так. Установка других приложений поверх вашего может привести к перезаписи ваших dll более старыми версиями. Более новые версии исчезнут. Это широко известно как «ад для dll», см. En.wikipedia.org/wiki/DLL_Hell
Адриан Григоре
1
Microsoft отказалась от WinSxS в Visual Studio 2010 - библиотеки времени выполнения теперь развертываются либо в частном порядке, либо в system32 ( msdn.microsoft.com/en-us/library/vstudio/dd293574.aspx ).
BCran
8

Проблема, с которой вы столкнетесь с / MD, заключается в том, что целевая версия CRT может не находиться на вашем компьютере пользователя (особенно если вы используете последнюю версию Visual Studio и у пользователя более старая операционная система).

В этом случае вам нужно выяснить, как установить нужную версию на их машину.

i_am_jorf
источник
7

из http://msdn.microsoft.com/en-us/library/2kzt1wy3(VS.71).aspx :

/ MT Определяет _MT, чтобы версии подпрограмм времени выполнения, специфичные для нескольких потоков, выбирались из стандартных файлов заголовков (.h). Этот параметр также заставляет компилятор поместить имя библиотеки LIBCMT.lib в файл .obj, чтобы компоновщик использовал LIBCMT.lib для разрешения внешних символов. Для создания многопоточных программ требуется / MT или / MD (или их отладочные эквиваленты / MTd или / MDd).

/ MD Определяет _MT и _DLL так, чтобы как многопоточные, так и специфичные для DLL версии подпрограмм времени выполнения выбирались из стандартных файлов .h. Этот параметр также заставляет компилятор помещать имя библиотеки MSVCRT.lib в файл .obj.

Приложения, скомпилированные с этим параметром, статически связаны с MSVCRT.lib. Эта библиотека предоставляет уровень кода, который позволяет компоновщику разрешать внешние ссылки. Фактический рабочий код содержится в MSVCR71.DLL, который должен быть доступен во время выполнения для приложений, связанных с MSVCRT.lib.

Когда / MD используется с определенным _STATIC_CPPLIB (/ D_STATIC_CPPLIB), это приведет к тому, что приложение будет связываться со статической многопоточной стандартной библиотекой C ++ (libcpmt.lib) вместо динамической версии (msvcprt.lib), при этом динамически связываясь с основной CRT через msvcrt.lib.

Итак, если я правильно интерпретирую, то / MT связывает статически, а / MD - динамически.

Лотар
источник
Вопрос был «какой из них использовать?», Это не ответ.
Леонард Инкрет,
2

Если вы создаете исполняемый файл, который использует другие dll или библиотеки, чем параметр / MD, предпочтительнее, потому что в этом случае все компоненты будут использовать одну и ту же библиотеку. Конечно, этот параметр должен соответствовать всем задействованным модулям, например dll / lib / exe.

Если ваш исполняемый файл не использует никаких библиотек или DLL, чем его чей-либо вызов. Сейчас разница не так велика, потому что аспект обмена не играет роли.

Так что, возможно, вы можете запустить приложение с помощью / MT, поскольку в противном случае нет веских причин, но когда пришло время добавить библиотеку или dll, вы можете изменить ее на / MD с помощью библиотеки lib / dll, что легко.

зар
источник