Компиляция C-файла с параметрами /c и /MD, затем связывание.lib-файлов

У меня есть файл C, который использует 3-4 внешних библиотеки. Он построен с использованием cl.exe а также link.exe(MSVC).

Сценарий сборки показывает, что процесс создания исполняемого файла состоит из двух этапов:

  • Используйте параметр '/c' с cl.exe чтобы получить .o файл. С этим также дается куча других флагов, но я обеспокоен тем, /MD, MSDN говорит:

Заставляет приложение использовать многопоточную и DLL-версию библиотеки времени выполнения. Определяет _MT и _DLL и заставляет компилятор поместить имя библиотеки MSVCRT.lib в файл.obj.

Какая польза от дачи /MD с cl когда мы только компилируем, а не линкуем?

  • После этого, link.exe используется для генерации exe Несколько .lib файлы указываются для ссылок (например, ole32.lib, advapi32.lib, user32.lib и т. д. и другие, не относящиеся к MSVC). Мой вопрос в том, что это не .lib файлы, используемые для статической ссылки? Если да, то почему итоговый exe всего около 500 кб? Ни один из .libs являются библиотеками импорта.

    Если нет, то делает link использовать статические или динамические ссылки по умолчанию? Ли /MD дано с cl есть какой-либо эффект здесь?

1 ответ

Решение

Изначально никогда не предполагалось, что оригинальная библиотека времени выполнения C будет поддерживать программы, построенные из нескольких модулей. Он содержит глобальные переменные, такие как errno а также stdout и функции, которые имеют неявное глобальное состояние, например strtok() а также malloc(), Вы можете связать библиотеки DLL с их собственной копией CRT, но это накладывает довольно жесткие требования на то, как вы проектируете интерфейс DLL. Вы должны быть очень осторожны, чтобы никогда не зависеть от состояния ЭЛТ. Понимание этого неверно приводит к почти невозможному диагностированию неправильного поведения во время выполнения.

Обходной путь для этого должен иметь только одну копию CRT в вашем процессе. Это то, что выполняет /MD, вы в конечном итоге получите зависимость от версии CRT, которая хранится в DLL. Разделяется всеми модулями. Как и msvcr120.dll, тот, который используется VS2013.

Компилятор должен знать это, чтобы он мог правильно использовать эту версию DLL. Простой пример errno, это глобальная переменная с /MT, но она макропрограммирована для вызова функции с /MD, так что только одна глобальная переменная внутри DLL когда-либо используется для отслеживания последнего известного значения. _DLL макрос будет определен, если действует /MD, используется в файлах.h компилятора.

Еще один побочный эффект заключается в том, что компилятор автоматически вставляет директиву link (эквивалентную #pragma comment) для msvcrt.lib или libcmt.lib. Предназначен для того, чтобы помочь вам избежать ошибок и исключить необходимость явного указания инструкции по подключению библиотеки CRT. Неправильное получение информации приводит к очень трудным диагностикам сообщений об ошибках компоновщика. Не отличается от того, который вы получаете, когда пытаетесь связать файлы.obj или.lib, созданные с несоответствием /MT и /MD. Что, конечно, не может работать должным образом, вы не можете зависеть от обоих.

Ни одна из.libs не является библиотеками импорта

Те, что вы перечислили по имени, ole32.lib, advapi32.lib, user32.lib, фактически являются библиотеками импорта. Это стандартные библиотеки операционной системы. Во время выполнения ваша программа загрузит соответствующие библиотеки DLL, легко видимые из отладчика. Для VS вы увидите это в окне вывода. Возможно, заслуживает внимания тот факт, что эти библиотеки DLL на самом деле используют другой CRT, чем ваша программа, они связываются с c:\windows\system32\msvcrt.dll. Винапи был тщательно разработан, чтобы никогда не создавать проблему.

по умолчанию ссылки используют статические или динамические ссылки

Там нет по умолчанию, это зависит от.lib вы ссылку. Различают статические библиотеки ссылок и библиотеки импорта. Библиотека импорта создается при сборке DLL. Это небольшой файл, который не содержит кода, только имена экспортируемых функций в DLL, поэтому компоновщик знает, как поместить запись в таблицу импорта программы. Зависимость DLL разрешается, и импортированные функции связываются загрузчиком при запуске программы.

Другие вопросы по тегам