Должен ли я компилироваться с /MD или/MT?

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

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

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

Некоторые вещи мне интересны:

  • Как это повлияет на время сборки? (предположительно/MT немного медленнее?)
  • Каковы другие последствия?
  • Какой из них использует большинство людей?

Ответ 1

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

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

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

Ответ 2

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

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

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

Ответ 3

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

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

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

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

Ответ 4

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

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

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

Ответ 5

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

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

Ответ 6

из 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, так что из стандартных файлов .h будут выбраны как многопоточные, так и DLL-версии исполняемых программ. Этот параметр также заставляет компилятор помещать имя библиотеки MSVCRT.lib в файл .obj.

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

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

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

Ответ 7

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

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

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