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

Вниз

Утечка памяти   Найти похожие ветки 

 
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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.5 MB
Время: 0.031 c
14-1078001008
VID
2004-02-28 23:43
2004.03.28
Мне нужен ваш совет


6-1074061465
olegking
2004-01-14 09:24
2004.03.28
Как получить имена или ИП всех компов находящихся в сети


14-1077811499
Zoloto
2004-02-26 19:04
2004.03.28
Создание скринсейвера


9-1063096418
GCreator
2003-09-09 12:33
2004.03.28
DMX...???


3-1077104740
sherminator
2004-02-18 14:45
2004.03.28
поиск по части поля





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский