Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2006.11.05;
Скачать: [xml.tar.bz2];

Вниз

Выделяем память в DLL, а освобождаем в главном приложении…   Найти похожие ветки 

 
gdaujk ©   (2006-09-26 13:29) [0]

Доброго времени суток, уважаемые Мастера.
Не так давно я спрашивал, как передавать данные в DLL без использования ShareMem. Сошлись на том, что выделение, освобождение и изменение размеров блока памяти должны происходить либо только в DLL, либо только в главном приложении.

Сейчас опять встретился с этой проблемой. Мне всё-таки хочется выделять память в DLL, а освобождать в главной программе. И показалось мне, что всего-то надо в библиотеке попросить памяти не у библиотечного менеджера кучи, а у менеджера главного приложения. Вот я и написал в DLL:

procedure FillArrWithMainMemMgr(MemMgr: TMemoryManager; var A: Pointer;
 aSize: Integer); stdcall;
var
 I: Integer;
begin
 A := MemMgr.GetMem(aSize * SizeOf(Real));
 for I := 0 to aSize - 1 do
   TRealArr(A)[I] := I;
end;


а в главном приложении:

type
 TRealArr = array of Real;

procedure TForm1.FormActivate(Sender: TObject);
var
 A: Pointer;
begin
 GetMemoryManager(MemMgr);
 FillArrWithMainMemMgr(MemMgr, A, 1000);
 Label1.Caption := FloatToStr(TRealArr(A)[5]);
 ReallocMem(A, 7*SizeOf(Double));
 Label2.Caption := FloatToStr(TRealArr(A)[6]);
 FreeMem(A);
end;


Всё работает вроде. Вы, может быть, меня параноиком сочтёте, но кажется мне, что что-то здесь неладно. Подскажите, может ли с этим кодом возникнуть проблемы, например, с последующими версиями Delphi или Windows? Пойдёт ли такая библиотека с приложениями на других языках?


 
Сергей М. ©   (2006-09-26 13:36) [1]


> И показалось мне, что всего-то надо в библиотеке попросить
> памяти не у библиотечного менеджера кучи, а у менеджера
> главного приложения


Ну и с чего ты взял, что хост-приложение обязано быть Делфи-приложением ?
Ты вон stdcall-спецификатор указал в объявлении ф-ции FillArrWithMainMemMgr, значит, ты заранее предполагаешь необязательность зазработки хост-приложения искл-но в делфи. А раз так, то о какой TMemoryManager может идти речь ?

Если уж на то пошло, то единым универсальным менеджером памяти д.б. такой менеджер, который известен приложениям, разработанным в любых средах разработки для соотв.платформы...


 
Reindeer Moss Eater ©   (2006-09-26 13:36) [2]

Подскажите, может ли с этим кодом возникнуть проблемы,

Обязательно возникнут недоумения у пользователей такой библиотеки.
Так как все нормальные люди с молоком матери впитали метдо двойного вызова принятый в Windows.
В первом вызове длл возвращает требуемый размер, а во втором сами данные в подготовленный буфер.


 
Сергей М. ©   (2006-09-26 14:05) [3]


> Reindeer Moss Eater ©   (26.09.06 13:36) [2]


Ну, положим, не везде и всюду там, в Виндовине, дело обстоит именно так ...но в целом и общем, т.е. в большинстве, оно именно так и обстоит)

Это я для пущей наглядности картины


 
Eraser ©   (2006-09-26 14:17) [4]

Еще, как вариант, можно для освобождения памяти вызывать спец. ф-ию из этой же библиотеки. Пример из виндовоза - WTSFreeMemory. Еще что пришло на память - у ISecurityInformation::GetSecurity своеобразный подход к работе с памятью.


 
gdaujk ©   (2006-09-26 14:30) [5]


> Сергей М. ©   (26.09.06 13:36) [1]


Ну stdcall я, честно, писал, что бы определить порядок передачи параметров. А менеджеры, отличающихся от Дельфийского, в конце концов, можно и привести к TMemoryManager.


> Reindeer Moss Eater ©   (26.09.06 13:36) [2]


Вы правы. И я тоже впитал. Только такая у меня задача, что о размере массива перед входом в DLL сказать можно только приблизительно. Выделять заведомо большее число элементов? Накладно. Постоянно просить главное приложение: «Дай ещё немножечко, мне не хватает», - или: «Заберите свои лишние  вшивые 100 байт»? Это пооригинальнее моего кода.

А так подсунул пользователю одну функцию и делоф. Можно ещё в интерфейсном модуле заметку оставить: «Память, выделенную сей функцией, повелеваю освобождать FreeMem’ом!»


 
gdaujk ©   (2006-09-26 14:33) [6]


> Eraser ©   (26.09.06 14:17) [4]


Специальная функция - дело хорошее, вот только, если пользователь не вызовет её - это будет моя вина, а если пользователь не вызовет FreeMem - его:-)


 
zamtmn ©   (2006-09-26 14:36) [7]

>>Пойдёт ли такая библиотека с приложениями на других языках?
такая не пойдет изза MemMgr: TMemoryManager - тут должен быть просто адрес процедуры выделяющей память а не TMemoryManager обертка.
в приведенном примере, размер массива известен еще в exe, зачем тут выделять память в dll?


 
Сергей М. ©   (2006-09-26 14:39) [8]


> gdaujk ©   (26.09.06 14:30) [5]


> stdcall я, честно, писал, что бы определить порядок передачи
> параметров


Меж прочим, stdcall не только оной предусматривает.


> менеджеры, отличающихся от Дельфийского, в конце концов,
>  можно и привести к TMemoryManager


Для тренировки приведи-ка к оному менеджер в составе набившего оскомину и всем до боли известного msvcrt.dll ..


 
gdaujk ©   (2006-09-26 15:09) [9]


> Сергей М. ©   (26.09.06 14:39) [8]

> Для тренировки


Первая пришедшая в голову концепция приведения к TMemoryManager:

type
 TMemoryManager = record
   GetMem: function(Size: Integer): Pointer;
   FreeMem: function(P: Pointer): Integer;
   ReallocMem: function(P: Pointer; Size: Integer): Pointer;
 end;

implementation

function OtherGetMem(Size: Integer): Pointer;
begin
 // TODO: выделение Size байт памяти с помощью
 // набившего оскомину и всем до боли известного msvcrt.dll
end;

function OtherFreeMem(P: Pointer): Integer;
begin
 // TODO: освобождение памяти с помощью
 // набившего оскомину и всем до боли известного msvcrt.dll
end;

function OtherReallocMem(P: Pointer; Size: Integer): Pointer;
begin
 // TODO: изменение размера блока памяти с помощью
 // набившего оскомину и всем до боли известного msvcrt.dll
end;

function GetOtherMemMgr: TMemoryManager;
begin
 Result.GetMem := OtherGetMem;
 Result.FreeMem := OtherFreeMem;
 Result.ReallocMem := OtherReallocMem;
end;



> zamtmn ©   (26.09.06 14:36) [7]

> тут должен быть просто адрес процедуры


Можно и так, только функций в DLL то хотелось бы иметь минимум две - выделение  и ресайзинг памяти.


 
Сергей М. ©   (2006-09-26 15:21) [10]


> gdaujk ©   (26.09.06 15:09) [9]



> Первая пришедшая в голову концепция приведения к TMemoryManager


Нормально пришедшая в нормальную голову нормальная концепция.

Ну и ?

Опробовал ?

Каковы результаты ?


 
zamtmn ©   (2006-09-26 15:32) [11]

>>Ну и ?
а че надо та?
в [0] собственно ниче такого нету, обычное решение экспорта распределяющих память процедур. все примерно так делают


 
zamtmn ©   (2006-09-26 15:34) [12]

разве что не таскать MemMgr: TMemoryManager в каждом вызове, а передать его в длл 1 раз после loadlibrary


 
gdaujk ©   (2006-09-26 15:44) [13]


> Сергей М. ©   (26.09.06 15:21) [10]


Если честно, вследствие своей неопытности мне до боли неизвестно, что такое msvcrt.dll. Посему не пробовал.

Но вопросы тут задаю я :-)) Вопрос: вы вчитаете, что для msvcrt.dll вариант [9] не годен? Если да, то почему?


> zamtmn ©   (26.09.06 15:32) [11]

> а че надо та?


Вот тоже очень интересный, но... не очень интеллигеннтный вопрос :-)


 
gdaujk ©   (2006-09-26 15:47) [14]


> zamtmn ©   (26.09.06 15:34) [12]


Мне вообще приходила мысль сразу после загрузки библиотеки подменить её менеджер на главный...


 
zamtmn ©   (2006-09-26 15:49) [15]

мой вопрос вобщето был к Сергей М.:)


 
Сергей М. ©   (2006-09-26 16:01) [16]


> для msvcrt.dll вариант [9] не годен?


Годен. Практически 100%-но.


> мне до боли неизвестно, что такое msvcrt.dll


Это такая хня, которую требуют чуть ли не стопроцентов сишного творчества.
Дельфийное же сооответственное творчество, как правило, после Д7 требует от тебя rtlXX.bpl, как "аналог" этой сишной ран-тайм-байды.


 
Игорь Шевченко ©   (2006-09-26 16:03) [17]


> Мне всё-таки хочется выделять память в DLL, а освобождать
> в главной программе


Это неправильно.


 
jack128 ©   (2006-09-26 16:04) [18]

gdaujk ©
Ты в курсе, с/с++ нутые компилеры (тот же MS"овский из студии) умеют генерить вызовы в register call convertion ??
Если нет, то тя ждет ОЙ. Ну, точнее, не тебя, а разработчика хост-приложения, ибо он просто не сможет написать, код, аналогичный [9]


 
zamtmn ©   (2006-09-26 16:08) [19]

>>Это неправильно.
а это спорно:)
выделение и освобождение происходит а exe, длл лишь вызываеть соответствующие процедуры. в программах с сложными динамическими структурами данных без этого оч. трудно обойтись


 
gdaujk ©   (2006-09-26 16:12) [20]


> Игорь Шевченко ©   (26.09.06 16:03) [17]


Я понимаю, что не правильно. А что делать?


> jack128 ©   (26.09.06 16:04) [18]


Помогите мне избежать "ОЙ", объясните, что значит "генерить вызовы"?


 
zamtmn ©   (2006-09-26 16:28) [21]

>>Ты в курсе, с/с++ нутые компилеры (тот же MS"овский из студии) умеют генерить вызовы в register call convertion ??

TMYMemoryManager =packed record
  GetMem: function(Size: Integer): Pointer;stdcall
.......
и проблем с конверсией вызовов и выравниванием небудет


 
Игорь Шевченко ©   (2006-09-26 16:48) [22]

zamtmn ©   (26.09.06 16:08) [19]


> а это спорно:)


Если времени много, тогда конечно, можно и помучиться


 
evvcom ©   (2006-09-27 09:19) [23]

2 gdaujk:
1. Обрати особое внимание на [2] и [3].
2. Все же разберись с тем, что такое соглашения о вызовах (calling convention), это такие директивы stdcall, cdecl, safecall.
3. Никогда не передавай дельфовые классы между exe и dll, если
 а) и exe, и dll компилируются без опции build with run-time packages
 б) dll планируется использовать в приложениях, написанных в средах, отличных от Delphi, или даже в другой версии Delphi.
4. Кроме Дельфового менеджера памяти имеется в ОС Windows функции WinAPI для выделения/перевыделения/освобождения памяти, см. GlobalAlloc, HeapAlloc, VirtualAlloc и другие соответствующие. Они могут быть использованы в любом приложении/библиотеке независимо от среды разработки. Дельфовый менеджер в конечном итоге сам их использует.



Страницы: 1 вся ветка

Форум: "Основная";
Текущий архив: 2006.11.05;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.51 MB
Время: 0.051 c
6-1150700215
Чайник2006
2006-06-19 10:56
2006.11.05
Как отправить файл на сервер с помощью idHTTP (Indy 10)


9-1138207783
Зм1й
2006-01-25 19:49
2006.11.05
Интерполяция матриц


8-1143547847
kmi
2006-03-28 16:10
2006.11.05
Как изменить бинарный файл?


15-1160985175
Kolan
2006-10-16 11:52
2006.11.05
Объект с разной ртруктурой..


15-1161166150
SerJaNT
2006-10-18 14:09
2006.11.05
Комп не грузиться=((





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский