C Run-Time библиотека часть 2 - PullRequest
4 голосов
/ 11 мая 2010

Мне предложили, когда у меня возникнут дополнительные вопросы по моим старым, создать новый вопрос и обратиться к старому. Итак, это оригинальный вопрос: Что такое библиотека времени выполнения C?

Хорошо, из ваших ответов я теперь получаю, что статически связанные библиотеки являются реализацией Microsoft стандартных функций языка C. Сейчас:

Если я правильно понял, схема будет следующей: я хочу использовать printf (), поэтому я должен включить <stdio.h>, который просто сообщает компилятору, что есть функция printf () с этими параметрами. Теперь, когда я компилирую код, так как printf () определен в стандартной библиотеке C, а Microsoft решила назвать ее библиотекой C Run Time, она автоматически статически связывается с libcmt.lib (если libcmt.lib установлен в компиляторе) в время компиляции. Я спрашиваю, потому что в википедии, в статье о библиотеке времени выполнения говорится, что библиотека времени выполнения связана во время выполнения, но файлы .lib связаны во время компиляции, я прав?

Теперь, что меня смущает. Существует стандартная версия библиотеки DLL языка C. Но я подумал, что для связывания DLL-файла вы должны вызвать winapi-программу для загрузки этой библиотеки. Итак, как эти функции могут быть динамически связаны, если нет статической библиотеки, предоставляющей код для Windows, чтобы загрузить нужные функции из dll?

И действительно, последний вопрос на эту тему - функции библиотеки C Standard также вызывают winapi, даже если они не являются файлами .dll, как более продвинутые функции WinAPI? Я имею в виду, что, в конце концов, чтобы получить доступ к кадровому буферу и напечатать что-то, вы должны сказать Windows сделать это, поскольку ОС не может позволить вам напрямую манипулировать HW. Я думаю об этом, как будто операционная система должна быть написана так, чтобы поддерживать все стандартные функции библиотеки C одинаково в разных версиях, поскольку они статически связаны и могут по-разному поддерживать более сложные вызовы WinAPI, потому что новая версия ОС может иметь настройки в файле DLL. .

Ответы [ 3 ]

3 голосов
/ 11 мая 2010

Чтобы ответить на ваши вопросы по порядку:

Википедия вводит вас в заблуждение. Библиотека времени выполнения не всегда связана во время выполнения , и не в том случае, если вы выбрали статически связанное время выполнения (libcmt.lib).

Существует .dll версия библиотеки времени выполнения (которая является связанной во время выполнения), и компилятор знает, как генерировать соответствующие инструкции в файле .exe, чтобы сказать загрузчику загрузить библиотека времени выполнения .dll во время выполнения.

Здесь есть два API. Одним из них является Win32 API, который представляет собой список функций, поддерживаемых самой ОС Windows. Другим API является API времени выполнения C, который определяется стандартом языка программирования C. Некоторые функции библиотеки времени выполнения C, такие как открытие и чтение файлов, в конечном итоге будут выполнять вызовы Win32 API для выполнения фактического файлового ввода-вывода. Другие функции библиотеки C, такие как, например, strlen(), не взаимодействуют с ОС и реализованы с использованием кода полностью внутри самой библиотеки времени выполнения.

2 голосов
/ 11 мая 2010

Связанная в C Run Time оболочка вокруг вашей «основной» функции; он инициализирует все, что нужно, прежде чем ваш код C может быть запущен. Он не содержит (m) никаких «функций», которые есть в стандартной библиотеке C (которая динамически связана).

Я думаю, вы неправильно понимаете динамическое связывание: оно выполняется ОС. Таким образом, вы сообщаете ОС, что вашему исполняемому файлу нужны DLL a, b, c и d. Когда вы выполняете свой исполняемый файл, ОС загружает исполняемый файл в ячейку памяти и считывает в исполняемом файле, что необходимо для его запуска. Затем он возьмет эти DLL и вставит их в область памяти вашего исполняемого файла, а затем сообщит вашему коду, что a загружен в x, b загружен в y и т. Д., Чтобы ваш код мог вызвать его функции.

Иногда компиляторы включают (так называемую статическую компоновку) библиотеку во время компиляции: они делают это так, чтобы ОС не загружала ее во время выполнения и, следовательно, загружала быстрее.

Файлы

.lib являются файлами DLL без буквы "D", поскольку они могут быть статически связаны. Также возможно динамически связываться с библиотечными файлами; это уменьшает размер исполняемого файла, но замедляет время загрузки исполняемого файла.

О WinAPI: большинство вызовов библиотеки C преобразуются в (некоторые) вызовы в WinAPI; но только если им приходится взаимодействовать с ОС (ввод-вывод и т. д.). Разница в том, что библиотека C одинакова на большинстве платформ, поэтому она увеличивает переносимость, если вы используете библиотеку C вместо Windows API напрямую.

Обновление

Вы спрашивали, как загрузить DLL, если вы полностью динамически связываете свой исполняемый файл? Ну, тебе не нужно! Разница между «загрузкой DLL» и «вызовом загрузки DLL» составляет; «загрузка dll» выполняется ОС при запуске приложения. ОС будет искать ваш исполняемый файл для определенной "таблицы импорта". Это таблица, в которой указывается, какие DLL ей действительно нужны , прежде чем она сможет выполняться (то есть kernel32.dll или user32.dll в Windows). ОС сделает "вызов для загрузки DLL", даже до запуска вашего кода.

"Call to load dll" также существует в kernel32.dll для вашего кода, который будет вызываться: есть возможность загружать / выгружать DLL, пока ваш код работает. Это может иметь место, если у вас огромная база кода и вы хотите освободить память, выгружая эту библиотеку одноразового использования в течение всего времени жизни вашего приложения (например, во время запуска). Если вы больше не используете эту функцию, вы можете выгрузить DLL. Но также возможно, что вам нужна какая-то функция, которую вы еще не загрузили, чтобы ускорить загрузку. Затем вы можете загрузить DLL, если вам нужна эта функция самостоятельно. Это довольно сложный процесс, и большую часть времени ОС все равно будет заменять неиспользуемые DLL-библиотеки (буквально «удаляя» память: она перемещает неиспользуемую память (например, неиспользуемую DLL) в массовое место хранилище, как на жестком диске. Если вам это нужно, оно автоматически «меняет» его обратно!).

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

1 голос
/ 11 мая 2010

В Visual C ++ и некоторых других компиляторах CRT связан для вас, если вы явно не скажете этого (иногда полезно для уменьшения размера кода).

В опциях компилятора вы можете выбрать, будут ли версии отладки или выпуска и будут ли они статически связаны или динамически.

Статическое связывание помещает весь фактический код из всех функций CRT, которые вы вызываете, прямо в ваш EXE-файл. Это полезно для уменьшения необходимого количества внешних зависимостей - вы можете просто запустить EXE и не беспокоиться о том, установлен ли у вас правильный файл xxxx.dll. Недостатком является то, что поставленные вами функции CRT могут иметь проблемы (эксплойты безопасности, сбои, условия гонки), и единственный способ, которым ваш конечный пользователь может решить эти проблемы, - это если вы создаете новый EXE-файл.

Динамическое связывание помещает ссылку на функции CRT, которые вы вызываете из вашего EXE. Когда ваш EXE загружается и ваш код вызывает вызываемую функцию, динамический загрузчик ОС увидит, что на самом деле эта функция находится в MSVCRT [D] [version] .dll, и загрузит эту DLL, найдите адрес функции а затем исправьте ссылку в вашем коде, чтобы она указывала непосредственно на функцию в DLL, чтобы в следующий раз она работала так же быстро, как если бы вы статически связывали ее. Ясно, что здесь есть начальная задержка запуска (по сравнению со статической связью), но преимущества огромны: системные DLL исправлены Microsoft, поэтому вы можете получать обновления проблем (см. Выше), загруженные DLL имеют shared in памяти, поэтому если DLL-библиотека, на которую вы ссылаетесь, уже используется другим процессом, ее загрузка займет меньше времени, поскольку другой процесс уже проделал большую работу.

Наконец, да, функции CRT, такие как printf () и scanf (), в конечном итоге взаимодействуют с Win32 API, но не всегда с теми, которые вы думаете. Используйте инструмент «DEPENDS» в Visual Studio / Windows SDK или «ProcExp» SysInternals, чтобы увидеть, какие DLL извлекаются каким-либо конкретным процессом и какие функции они используют.

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