почему это работает?
От: nen777w  
Дата: 13.10.06 07:17
Оценка:
известно что у 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



Кто то может объяснить почему?
Спасибо.
Re: почему это работает?
От: Сергей  
Дата: 13.10.06 07:21
Оценка:
Здравствуйте, nen777w, Вы писали:

N>По идее приложение не может управлять (вызывать методы) у такого объекта, т.к. таблица виртуальных ф-ций лежит в куче dll, но

N>каким то чудным образом это работает.

Почему же не может? Адресное пространство одно и то же, в чем проблема?
Re: почему это работает?
От: Bell Россия  
Дата: 13.10.06 07:31
Оценка:
Здравствуйте, 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, или получая оттуда, а потом бросили это занятие из-за непонятных ошибок, возникающих в вашей программе, то эта заметка для вас. Даже если видимых проблем в вашей программе нет, то все равно прочитайте эту заметку, чтобы знать что делать, когда они появятся :)
Любите книгу — источник знаний (с) М.Горький
Re: почему это работает?
От: Left2 Украина  
Дата: 13.10.06 08:26
Оценка:
Ко всему прочему, сами таблицы виртуальных функций в куче не лежат никогда. Там лежат только указатели на эти таблицы — и то, только для классов созданных в куче.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: почему это работает?
От: Кодт Россия  
Дата: 13.10.06 09:10
Оценка:
Здравствуйте, 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>>
Перекуём баги на фичи!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.