Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 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.5 MB
Время: 0.05 c
14-1077979354
Шишкин Илья
2004-02-28 17:42
2004.03.28
Проблема с железом


3-1077137878
ser_ega
2004-02-18 23:57
2004.03.28
BDE


1-1079013992
Thick
2004-03-11 17:06
2004.03.28
Компонент в RichEdit


14-1077964876
NailMan
2004-02-28 13:41
2004.03.28
Фотки с MMP(как и обещал вчера)


6-1073837038
Iks
2004-01-11 19:03
2004.03.28
Передача изображения по сети