2010-05-10 4 views
4

Мне предложили, когда у меня возникнут дополнительные вопросы о моих старых, чтобы создать новый вопрос и обратиться к старой. Итак, это оригинальный вопрос: What is the C runtime library?C Библиотека времени выполнения 2

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

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

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

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

ответ

2

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

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

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

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

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

Update:

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

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

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

+0

Спасибо за ваш ответ. Думаю, я правильно понимаю dll. Я, когда вы хотите загрузить некоторую dll напрямую в другую статически связанную программу, вы должны вызвать WinAPI для этого. Итак, как вы называете ОС для загрузки dll, когда ваша единственная библиотека - это dll? –

3

Для решения ваших вопросов в порядке:

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

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

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

+0

ОК, спасибо. Я знаю, что некоторые стандартные функции библиотеки C не нуждаются в вызовах ОС, например, все функции math.h. –

+0

И для некоторых функций, таких как strlen(), они могут быть реализованы компилятором в виде встроенных ассемблерных вставок - возможно, не в Windows с помощью MSVC, а на других платформах с другими компиляторами. –

+0

@ Джонатан Леффлер: MSVC фактически обладает широким спектром таких внутренних функций: http://msdn.microsoft.com/en-us/library/26td21ds.aspx –

1

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

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

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

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

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

Смежные вопросы