В Windows и OS/2 используется именно такой способ загрузки. Исполняемый модуль в этих системах содержит ссылки на другие модули, называемые DLL (Dynamically Loadable Library, динамически загружаемая библиотека). Фактически, каждый модуль в этих системах обязан содержать хотя бы одну ссылку на DLL, потому что интерфейс к системным вызовам в этих ОС также реализован в виде DLL.
DLL представляют собой библиотеки в том смысле, что обычно они собираются из нескольких объектных модулей. Но, в отличие от архивных библиотек, из DLL нельзя извлечь отдельный модуль, при присоединении библиотеки к программе она присоединяется и загружается целиком.
Главное достоинство DLL состоит в том, что модуль (как основной, так и библиотечный), по собственному желанию, может выбирать различные библиотеки, подгружая их уже после своей собственной загрузки. При этом нет даже строгого ограничения на совместимость этих библиотек по вызовам (две библиотеки совместимы по вызовам, если они имеют одинаковые точки входа с одинаковой семантикой): загрузчик предоставляет возможность просмотреть список глобальных символов, определенных в библиотеке и получить указатель на каждый символ, обратившись к нему по имени; (впрочем, количество и типы параметров или тип переменной, а тем более их семантику, загрузчик не сообщает - эту информацию надо получать из других источников, например из списка зарегистрированных в системе объектов СОМ).
Особенно удобна возможность вызывать любую функцию по имени при обращении к внешним модулям из интерпретируемых языков. DLL являются удобным средством разделения кода и создания отделы загружаемых программных модулей, но их использование сопряжено с определенной проблемой, которая будет подробнее объясняться в разд. 5.4. Забегая вперед, скажем, что концепция разделяемых DLL наиболее естественна в системах, где все задачи используют единое адресное пространство - но при этом ошибка в любой из программ может привести к порче данных или кода другой задачи. Стандартный же способ борьбы с этой проблемой — выделение каждому процессу своего адресного пространства, значительно усложняет разделение кода.
Другая проблема, обусловленная широким использованием разделяемого кода, состоит в слежении за версией этого кода.