Текущий архив: 2004.03.28;
Скачать: CL | DM;
Вниз
Утечка памяти Найти похожие ветки
← →
bjohny (2004-03-07 11:20) [0]Привет. Проблема с утечкой памяти. Создаю MDI приложение, с меню. Child окна загружаются из DLL, библиотека загружается когда кликаешь на пункте меню, и выгружается, когда закрывается Child окно(для этого Child посылает сообщение родительскому окну). Библиотека выгружается, но память почему-то полностью не выгружается(размер приложения в исходный/без Child/ не возвращается). Помогите разобраться в чем проблема.
Привожу исходники.
Главная Форма:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Menus;
type
TForm1 = class(TForm)
MainMenu1: TMainMenu;
Add1: TMenuItem;
procedure Add1Click(Sender: TObject);
private
{ Private declarations }
procedure Closed(Var Mes:TMessage); message wm_user+10;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Closed(Var Mes:TMessage);
var H:THandle;
i:integer;
des:procedure; stdcall;
begin
// Сообщение о закрытии окна, выгружаем DLL
H:=Mes.LParam;
@Des:=nil;
if H>32 then
begin
try
@des := GetProcAddress(h, "DonePlugin");
if @des<>nil then
des;
finally
FreeLibrary(H);
end;
end;
end;
procedure TForm1.Add1Click(Sender: TObject);
var CreateReferences:function (ParentHandle, DllH:THandle):TForm; StdCall;
Ptr:procedure(App, Src:Integer); stdcall;
Handle1:THandle;
begin
// Загружаем DLL
try
@CreateReferences:=nil;
handle1 := LoadLibrary(pchar("Form0"));
if handle1 <> 0 then
@ptr := GetProcAddress(handle1, "InitPlugin");
if @ptr<>nil then
ptr(integer(Application), integer(Screen))
else
raise Exception.Create("Cant initialize plugin on ");
@CreateReferences := GetProcAddress(handle1, "CreateReferences");
if @CreateReferences <> nil then
begin
CreateReferences(self.Handle, Handle1);
end
else
raise Exception.Create("Cant open ");
except
On E:Exception do
begin
Application.MessageBox(PChar(E.Message),"Error",mb_ok or mb_iconstop);
FreeLibrary(Handle1);
end;
end;
end;
end.
Dll для Child:library Form0;
uses
Sharemem,
dialogs,
Forms,
SysUtils,
Unit2 in "Unit2.pas";
var
DLLApp: TApplication;
DLLScr: TScreen;
References:TForm2;
{$R *.res}
procedure InitPlugin(App, Scr: integer); StdCall;
begin
DLLScr := Screen;
Screen := TScreen(Scr);
DLLApp := Application;
Application := TApplication(App);
end;
procedure DonePlugin; StdCall;
begin
Screen := DLLScr;
Application := DLLApp;
end;
function CreateReferences(ParentHandle, dllH:THandle):TForm; StdCall;
begin
References:=TForm2.Create(Application);
References.ParentHandle:=ParentHandle;
// В Caption Пишем хэндл DLL чтобы потом отправить его родителю
References.Caption:=References.Caption+"["+IntToStr(DllH)+"]";
Result:=References;
end;
exports
InitPlugin,
DonePlugin,
CreateReferences;
begin
end.
Child:
unit Unit2;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm2 = class(TForm)
Button1: TButton;
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
parenthandle:THandle;
end;
var
Form2: TForm2;
implementation
{$R *.dfm}
procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action:=caFree;
end;
procedure TForm2.FormDestroy(Sender: TObject);
begin
// Отправка сообщения о закрытии окна, с хендлом DLL
PostMessage(parentHandle, wm_user+10,Self.Handle,StrToInt(Copy(self.Caption,pos("[",self.Caption)+1,pos("]",self.Caption)-pos("[",self.Caption)-1) ));
end;
end.
← →
Cobalt © (2004-03-08 01:16) [1]Как определяете утчку?
Рекомендую попробовать MemProof.
← →
Германн © (2004-03-08 01:58) [2]2 bjohny (07.03.04 11:20)
А уж это совсем не понятно:
"размер приложения в исходный/без Child/ не возвращается"?
Что есть "размер приложения" ?
← →
Mim (2004-03-08 09:00) [3]Сейчас делаю нечто подобное, я бы вам посоветовал компилировать ваш проект с использованием runtime библиотек vcl70 и тп,
поскольку модуль forms находится внутри этих bpl то нет необходимости передовать ссылки на tapplication и tscreen, да и размер программы вместе с плагинами значительно уменьшится.
+ в глаза бросается такая строка// Отправка сообщения о закрытии окна, с хендлом DLL
PostMessage(parentHandle, wm_user+10,Self.Handle,StrToInt(Copy(self.Caption,pos("[",self.Caption)+1,pos("]",self.Caption)-pos("[",self.Caption)-1) ));
Вот такого делать StrToInt(Copy(self.Caption,pos("[",self.Caption)+1,pos("]",self.Caption)-pos("[",self.Caption)-1) ));
крайне не желательно
← →
Mim (2004-03-08 09:02) [4]простите мою бестактность
может есть идеи относительно
http://delphimaster.net/view/1-1078606263/
← →
bjohny (2004-03-08 09:48) [5]Утечка памяти определяется через TaskManager. Размер занимаемой памяти приложением увеличивается. Под размером приложения понимается чистое родительское окно, без чилдов. Компиляция с Run-Time пакетами ситуациине изменят. Строка StrToInt(Copy(self.Caption,pos("[",self.Caption)+1,pos("]",self.Caption)-pos("[",self.Caption)-1) )); сделана просто в этом примере, в реальности в LParam передается просто 0.
← →
riko (2004-03-08 10:39) [6]Посмотрите ответ [1]. TaskManager не для этого.
Лучше воспользоваться специально предназначенным
для этого инструментом.
← →
Mim (2004-03-08 10:49) [7]bjohny (08.03.04 09:48) [5]
Когда делаете postmessage hinstance библиотеки можно вычислить например такFindClassHInstance(self.ClassType)
Действительно ли правильно отрабатывает
procedure TForm1.Closed(Var Mes:TMessage); ?
Возможно память не освобождается изза некого кэширующего механизма windows.
← →
bjohny (2004-03-08 11:03) [8]Да, действительно. Утечки нет. Тогда еще один вопрос.
В итоговом проекте если вызывать формы с одинаковым набором компонент(Например форма с String Grid), то все ок. Если открыть две разные формы(Форму со StringGrid и форму с полями для заполнения данных о сотруднике/ФИО и т.д./ ) несколько раз, то вылетает AV что TFont не может быть создан(если память не изменят).
Используются TMS компоненты. Может есть какие нить соображения, как это побороть?
← →
Mim (2004-03-08 11:11) [9]Я отказался от использования этих копонент по причине их глючности и отсутствия исходных текстов. Если у вас нет исходников то тоже откажитесь от них, иначе рано или поздно вощзникнет ситуация когда отсутствие исходных текстов поставит вас в тупик.
← →
bjohny (2004-03-09 08:11) [10]Исходники есть.
← →
bjohny (2004-03-09 10:18) [11]Может кто подскажет какой-нить StringGrid с такими же функциями как и у TMS(Скрытие столбцов и т.д.)
← →
REA © (2004-03-09 10:29) [12]В разных DLL (и самом exe) разные таблицы классов, поэтому присвоения классов между ними недопустимы. Возможно отсюда и ошибка со шрифтом (TFont cannot be assigned to TFont).
Страницы: 1 вся ветка
Текущий архив: 2004.03.28;
Скачать: CL | DM;
Память: 0.49 MB
Время: 0.022 c