ale*_*oot 3 delphi memory-leaks delphi-7 kylix clx
我遇到了Delphi 7应用程序(CLX)的内存泄漏问题,其代码如下:
unit Unit2;
interface
uses ECRClass, ECR_Text, SysUtils, Types, Classes, Variants, Math;
type tLeakClass = class
private
fsType : integer;
public
fsPrinter : TECR_Class;
published
constructor Create (AOwner : TComponent);
destructor Destroy();
end;
implementation
constructor tLeakClass.Create (AOwner : TComponent);
begin
fsPrinter := TECR_Text.Create(AOwner);
end;
destructor tLeakClass.Destroy();
begin
fsPrinter.Free
end;
end.
Run Code Online (Sandbox Code Playgroud)
fsPrinter即使在主窗体(TForm)关闭时释放它,对象结果也会泄露:
unit Unit1;
interface
uses
SysUtils, Types, Classes, Variants, QTypes, QGraphics, QControls, QForms,
QDialogs, QStdCtrls, Unit2;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
tleak : tLeakClass;
end;
var
Form1: TForm1;
implementation
{$R *.xfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
tLeak := tLeakClass.Create(Self);
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
tleak.Free
end;
end.
Run Code Online (Sandbox Code Playgroud)
以下是FastMM4的泄漏报告:
A memory block has been leaked. The size is: 740
This block was allocated by thread 0xBA8, and the stack trace (return addresses) at the time was:
402F1C [system.pas][System][@GetMem][2439]
403C77 [system.pas][System][TObject.NewInstance][8360]
404012 [system.pas][System][@ClassCreate][9019]
502F15 [ECR_Text.pas][ECR_Text][TECR_Text.Create][101]
403C80 [system.pas][System][TObject.NewInstance][8360]
404012 [system.pas][System][@ClassCreate][9019]
5030C6 [Unit2.pas][Unit2][tLeakClass.Create][24]
43856C [QStdCtrls.pas][QStdCtrls][2863]
503300 [Unit1.pas][Unit1][TForm1.Button1Click][30]
447076 [QControls.pas][QControls][TControl.Click][1977]
43858C [QStdCtrls.pas][QStdCtrls][TButton.Click][2871]
The block is currently used for an object of class: TECR_Text
Run Code Online (Sandbox Code Playgroud)
在这里,您可以下载代表问题的项目的完整SSCCE示例(单击按钮运行示例并关闭表单).
fsPrinter对象泄漏的原因是什么?我怎样才能避免泄漏?
您的析构函数声明不正确.你写了:
destructor Destroy();
Run Code Online (Sandbox Code Playgroud)
但是您必须覆盖声明的虚拟析构函数TObject.如果不这样做,那么析构函数将不会被Free虚拟析构函数声明的调用调用TObject.
修复如下:
destructor Destroy(); override;
Run Code Online (Sandbox Code Playgroud)
虽然在这种情况下无关紧要,但您应该养成在构造函数和析构函数中调用继承的构造函数和析构函数的习惯.这样,当你从一个比TObject它的构造函数和析构函数更多的类派生时,你将确保运行超类代码.
constructor tLeakClass.Create (AOwner : TComponent);
begin
inherited Create;
fsPrinter := TECR_Text.Create(AOwner);
end;
destructor tLeakClass.Destroy();
begin
fsPrinter.Free;
inherited;
end;
Run Code Online (Sandbox Code Playgroud)
FastMM报告虽然有点奇怪.它报告该TECR_Text对象泄露.但是,由于您创建了表单所拥有的内容,因此表单应该将其删除.在问题的代码中明显泄露的对象是实例tLeakClass
所以我怀疑在课堂上还有其他问题我们看不到.很可能你犯了同样的错误,省略了override我们看不到的类的析构函数.