Должен ли я компилироваться с /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, что легко.