Поведение библиотеки времени выполнения
Обновлен: Ноябрь 2007
Код библиотеки времени выполнения языка C или C++ производит последовательный запуск библиотеки DLL, исключая необходимость связи с отдельным модулем, наличие которой было обязательным в Windows 3.x. Включенный в библиотеку времени выполнения код C или C++ представляет собой функцию точки входа библиотеки DLL с именем _DllMainCRTStartup. Функция _DllMainCRTStartup выполняет несколько задач, в число которых входит вызов функции _CRT_INIT, инициализирующий библиотеку времени выполнения языка C или C++, и вызов конструкторов C++ для статических, нелокальных переменных. Без этой функции библиотека времени выполнения останется в неинициализированном состоянии. Функция _CRT_INIT доступна как для статически скомпонованной CRT, так и для скомпонованной с CRT DLL Msvcr90.dll из пользовательской библиотеки DLL.
Хотя существует возможность указания другой функции точки входа с использованием параметра компоновщика /ENTRY:, применять ее не рекомендуется, поскольку в этом случае работа функции точки входа заключается в копировании всего, что создает функция _DllMainCRTStartup. Во время построения библиотеки DLL в Visual C++ функция _DllMainCRTStartup компонуется автоматически и функцию точки входа, указывать функцию точки входа с использованием параметра компоновщика /ENTRY: не требуется.
В дополнении к инициализации библиотеки времени выполнения языка C, функция _DllMainCRTStartup вызывает функцию с именем DllMain. В зависимости от типа библиотеки DLL, построение которой выполняется, Visual C++ предоставляет объект DllMain, который возвращается скомпонованным, поэтому функция _DllMainCRTStartup всегда вызывает что-либо. В таком случае, если инициализация DLL не требуется, и во время построения DLL не нужно производить дополнительные действия. Если инициализировать DLL все же необходимо, то точка, куда следует добавить код, зависит от типа DLL. Дополнительные сведения см. в разделе Инициализация библиотеки DLL.
Код библиотеки времени выполнения C/C++ вызывает конструкторы или деструкторы для статических, нелокальных переменных. Например, в следующем исходном коде DLL объекты Equus и Sugar являются статическими, нелокальными объектами класса CHorse, определенного в файле Horses.h. В исходном коде нет функции, которая содержала бы вызов конструктора или деструктора для объекта CHorse, поскольку данные объекты определены вне любой функции. Поэтому код времени выполнения должен выполнять вызов этих конструкторов и деструкторов. Код библиотеки времени выполнения для приложений также производит вызов данной функции.
#include "horses.h"
CHorse Equus( ARABIAN, MALE );
CHorse Sugar( THOROUGHBRED, FEMALE );
BOOL WINAPI DllMain (HANDLE hInst,
ULONG ul_reason_for_call,
LPVOID lpReserved)
...
Каждый раз, когда новый процесс пытается использовать библиотеку DLL, операционная система создает отдельную копию данных библиотеки DLL: это называется присоединением процесса. Код библиотеки времени выполнения для библиотеки DLL вызывает конструкторы для всех глобальных объектов, если такие существуют, а затем вызывает функцию DllMain с выбранным присоединением процесса. Обратная ситуация — отсоединение процесса: код библиотеки времени выполнения вызывает функцию DllMain с выбранным отсоединением процесса и затем вызывает список функций завершения процессов, включающий функции atexit, деструкторы для глобальных объектов и деструкторы для статичных объектов. Обратите внимание, что порядок событий присоединения процесса является обратным порядку событий отсоединения процесса.
Код библиотеки времени выполнения также вызывается во время присоединения и отсоединения потока, но код времени выполнения не выполняет инициализацию или завершение самостоятельно.