Почему компоновщик C ++ требует файлы библиотеки во время сборки, даже если я динамически компоноваю? - PullRequest
14 голосов
/ 08 января 2010

У меня есть исполняемый файл C ++, и я динамически связываюсь с несколькими библиотеками (Boost, Xerces-c и пользовательскими библиотеками).

Я понимаю, почему мне потребуются файлы .lib / .a, если я решу статически связываться с этими библиотеками ( соответствующий вопрос SO здесь ). Однако зачем мне указывать соответствующие файлы библиотеки .lib / .so при компоновке моего исполняемого файла, если я динамически подключаюсь к этим внешним библиотекам?

Ответы [ 6 ]

8 голосов
/ 08 января 2010

Компилятор не знает о динамическом линковании, он просто знает, что функция существует через свой прототип. Компоновщику нужны файлы lib для разрешения символа. Библиотека DLL для DLL содержит дополнительную информацию, например, о том, в какой библиотеке DLL находятся функции и как они экспортируются (по имени, по порядковому номеру и т. Д.). Файлы lib для DLL содержат гораздо меньше информации, чем файлы lib, которые содержат полный объектный код - libcmmt .lib в моей системе - 19,2 МБ, но msvcrt.lib - только 2,6 МБ.

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

2 голосов
/ 08 января 2010

Рэймонд Чен написал пару записей в блоге об этом, специфичном для Windows. Начните с Классическая модель для связывания , а затем перейдите к Почему у нас все-таки есть библиотеки импорта? .

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

Причина, по которой .DLL не имеют всей информации, которая необходима для прямой связи с ними, является исторической, а не техническим ограничением.

1 голос
/ 08 января 2010

У компоновщика есть задача проверить, учитываются ли все ваши неопределенные символы, как со статическим, так и с динамическим контентом.

По умолчанию он настаивает на наличии всех ваших символов.

Однако это просто по умолчанию. Смотрите -z, --allow-shlib-undefined и друзья.

1 голос
/ 08 января 2010

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

0 голосов
/ 08 января 2010

Вот очень упрощенное описание, которое может помочь.Статическое связывание помещает весь код, необходимый для запуска вашей программы, в исполняемый файл, чтобы все было найдено.Динамическое связывание означает, что часть необходимого кода не помещается в исполняемый файл и будет найдена во время выполнения.Где я могу найти это?Функция x () есть?Как мне сделать вызов функции x ()?Это то, что библиотека сообщает компоновщику, когда вы динамически связываете.

0 голосов
/ 08 января 2010

Возможно, это динамическое связывание выполняется через библиотеки импорта (функция имеет __declspec (dllimport) перед определением).
Если это так, то компилятор ожидает, что объявлена ​​функция __imp_symbol, и эта функция отвечает за динамическую загрузку вызова в нужную библиотеку.
Эти функции создаются при связывании символов с ключевым словом __declspec (dllimport)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...