Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Memory Leak and AV with MDIChild forms in DLL

Status
Not open for further replies.

mattlacey

Programmer
Oct 11, 2001
22
0
0
GB
I have created an application that contains mdi-child forms in DLLs. This is all working fine except that doing anything with the DLLs is causing memory leaks (As indicated by MemorySleuth2).

Also, I can't close my child forms from the parent without causing access violations. These lock the program up. If I close the child forms individually, then the app will close fine.

This code sample contains the bare minimum to show what I'm doing and demonstrate the error. In reality there are multiple DLLs and each DLL may contain multiple forms.


Any help/pointers/suggestions/etc. greatly appreciated

***********************
main (mdi) form
***********************

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TShowFrm = procedure(App: TApplication; Scr:TScreen); stdcall;

type
TForm1 = class(TForm)
Button2: TButton;
procedure FormCreate(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure Button2Click(Sender: TObject);
private
hInstance: THandle;
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
try
hInstance := SafeLoadLibrary('Mydll.dll', SEM_NOOPENFILEERRORBOX);
{load the library on form create as will need to know what forms are
available, so they can be listed for creation.}
except
on e: exception do ShowMessage(e.Message);
end;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
try
if Form1.MDIChildCount = 1 then
begin
MDIChildren[0].Close;
end;
{This example only uses 1 form in a single dll. In reality would cycle
through all open children, closing as go}

FreeLibrary(hInstance);
{destroy reference to dll}
except
on e: exception do ShowMessage(e.Message);
end;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
AFunc: Pointer;
begin
try
Pointer(AFunc) := GetProcAddress(hInstance, PChar ('ShowFrm'));
TShowFrm(AFunc)(Application, Screen);
{Open the child form}
except
on e: exception do ShowMessage(e.Message);
end;
end;

end.


***********************
dll file
***********************

library Mydll;

uses
SysUtils,
Classes,
Forms,
Windows,
Dialogs,
MyForm in 'MyForm.pas' {Form2};

{$R *.res}

var
AppDLL: TApplication;
ScrDLL: TScreen;

procedure MyDLLProc(Reason: Integer);
begin
try
if Reason = DLL_PROCESS_DETACH then
begin
Application := AppDLL;
Screen := ScrDLL;
end;
except
on e: exception do ShowMessage(e.Message);
end;
end;

procedure ShowFrm(App:TApplication; Scr: TScreen); stdcall;
begin
Application := App;
Screen := Scr;
App.CreateForm(TForm2, Form2);
Form2.Show;
end;

exports
ShowFrm;

begin
try
AppDLL := Application;
ScrDLL := Screen;
DLLProc := @MyDLLProc;
except
on e: exception do ShowMessage(e.Message);
end;
end.


***********************
mdi-child form
***********************

unit MyForm;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TForm2 = class(TForm)
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form2: TForm2;

implementation

{$R *.dfm}

procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
try
Action := caFree;
except
on e: exception do ShowMessage(e.Message);
end;
end;

end.


 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top