известно что у dll подгружаемой динамически и приложения две разные кучи памяти и две разные точки входа.
допустим у dll есть глобальная ф-ция создающая некоторый объект типа class возвращаемый приложению.
класс экспортится / импортиться через дериктиву __declspec(dllexport / dllimport)
По идее приложение не может управлять (вызывать методы) у такого объекта, т.к. таблица виртуальных ф-ций лежит в куче dll, но
каким то чудным образом это работает.
т.е. в коде это вот так примерно:
HMODULE hM = LoadLibrary("some.dll");
m_pfnSomeGlobalProcCreateClassSomeClass = GetProcAdress(hM, "SomeGlobalProcCreateClassSomeClass");
SomeClassBase* p = m_pfnSomeGlobalProcCreateClassSomeClass();
p->call_virtual_method(); //ok
p->call_non_virtual_method(); //ok
Кто то может объяснить почему?
Спасибо.
Здравствуйте, nen777w, Вы писали:
N>известно что у dll подгружаемой динамически и приложения две разные кучи памяти и две разные точки входа.
N>допустим у dll есть глобальная ф-ция создающая некоторый объект типа class возвращаемый приложению.
N>класс экспортится / импортиться через дериктиву __declspec(dllexport / dllimport)
N>По идее приложение не может управлять (вызывать методы) у такого объекта, т.к. таблица виртуальных ф-ций лежит в куче dll, но
N>каким то чудным образом это работает.
N>т.е. в коде это вот так примерно:
N>N>HMODULE hM = LoadLibrary("some.dll");
N>m_pfnSomeGlobalProcCreateClassSomeClass = GetProcAdress(hM, "SomeGlobalProcCreateClassSomeClass");
N>SomeClassBase* p = m_pfnSomeGlobalProcCreateClassSomeClass();
p->>call_virtual_method(); //ok
p->>call_non_virtual_method(); //ok
N>
N>Кто то может объяснить почему?
exe и dll находятся в одном адресном прострастве, поэтому указатели, полученные из dll могут совершенно спокойно использоваться в exe и наоборот.
Проблемы возможны при выделении/освобождении ресурсов в разных модулях. Подробнее можно посмотреть, например,
здесьАвтор(ы): Роман Хациев
Дата: 27.02.2002
Если вы пытались работать с экземплярами классов STL, передавая их в DLL, или получая оттуда, а потом бросили это занятие из-за непонятных ошибок, возникающих в вашей программе, то эта заметка для вас. Даже если видимых проблем в вашей программе нет, то все равно прочитайте эту заметку, чтобы знать что делать, когда они появятся :)
Ко всему прочему, сами таблицы виртуальных функций в куче не лежат никогда. Там лежат только указатели на эти таблицы — и то, только для классов созданных в куче.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Здравствуйте, nen777w, Вы писали:
N>известно что у dll подгружаемой динамически и приложения две разные кучи памяти и две разные точки входа.
N>допустим у dll есть глобальная ф-ция создающая некоторый объект типа class возвращаемый приложению.
N>класс экспортится / импортиться через дериктиву __declspec(dllexport / dllimport)
N>По идее приложение не может управлять (вызывать методы) у такого объекта, т.к. таблица виртуальных ф-ций лежит в куче dll,
Таблицы виртуальных функций — это статические массивы, они лежат в секции констант.
Связывание ссылок на vtbl в коде с положением её в адресном пространстве занимается загрузчик в момент LoadLibrary. И делает это корректно, равно как корректно связывает ссылки на любые (экспортируемые и приватные) функции, статические данные и т.п.
N> но каким то чудным образом это работает.
Чужой кучей нельзя управлять (т.е. нельзя взять блок памяти, выделенный чужим менеджером, и отдать на удаление своему).
А доступаться к памяти — сколько угодно. Адресное пространство-то общее.
Представь себе, что есть функции
void* alloc_1(size_t count);
void free_1(void* p);
void* alloc_2(size_t count);
void free_2(void* p);
Естественно, что указатель, полученный из alloc_1, нельзя скормить free_2, и наоборот.
Смущение вызывает лишь то, что имена у функций на самом деле одинаковые (malloc/free)
хотя относятся они к разным модулям, и соответственно, разным менеджерам памяти.
Но если и exe, и dll скомпилированы с одинаковой версией DLL CRT, то менеджер будет общий.
... << RSDN@Home 1.2.0 alpha rev. 655>>