我看到的唯一方法是为此添加标志,但这是最好的方法吗?
当表单被销毁时,我检查是否(Assigned(form2))结果为真?为什么?
这样做的方法是什么?
我有以下Delphi代码:
destructor TXX_XXXX.Destroy;
var
i: Integer;
begin
if Assigned(Allocations) then
begin
for i:=0 to (Allocations.Count - 1) do
begin
try
TXX_ALOC(Allocations.Items[i]).Free;
except on Ex:Exception do
begin
OutputDebugString(PChar('Exception Error Message '+ Ex.Message));
end;
end;
end;
// Above code works well - no exception
try
FreeAndNil(Allocations); {Exception Here}
except on E:Exception do
begin
OutputDebugString(PChar('Exception in xxxxxxxxx.pas'+E.Message));
end;
end;
end;
inherited;
end;
Run Code Online (Sandbox Code Playgroud)
模块"Vcl50.bpl"中地址4003AB4处的访问冲突.读取地址2980BFFC
我知道通常由访问冲突引起的
但是在我免费之前,我检查了Allocations.如果我放弃异常处理,我的应用程序会抛出一些错误的错误.分配是一个TObjectList,如果它是一个数组 - 我会怀疑我没有给数组分配一个长度,但它是一个TObjectList.
非常感谢!
情况
我正在从Marco Cantu的书中学习Delphi,我已经有了OOP的经验,因为我经常使用Java和PHP.为了更好地理解我正在阅读的内容,我做了这个测试:
type
TFraction = class
private
number: double;
num, den: integer;
fraction: string;
function hcf(x: integer; y: integer): integer;
public
constructor Create(numerator: integer; denominator: integer); overload;
constructor Create(value: string); overload;
function getFraction: string;
end;
Run Code Online (Sandbox Code Playgroud)
这是一个超级简单的类,它将十进制数转换为分数.我不包括我定义构造函数和函数的代码的其他部分,因为它们对我的问题没用.我以这种方式创建对象.
var a: TFraction;
begin
a := TFraction.Create(225, 35);
ShowMessage(a.getFraction);
//The output of ^ is 45/7
a.Free;
end;
Run Code Online (Sandbox Code Playgroud)
题
据我所知,我知道一旦我使用它就必须摆脱它,事实上我正在使用它Free.通过这种方式,我释放内存,避免内存泄漏.
顺便说一句,我看到我也有可能覆盖一个destructor.我不很了解的行为Free和Destroy.我使用的Free时候我必须摆脱一个我不再需要的物体.当我覆盖析构函数时,我可以释放对象并进行其他操作吗?
简而言之,什么时候使用免费?什么时候我应该更喜欢毁灭?
注意:请耐心等待,由于此处和此处的一些讨论以及我在此处和此处报告的一些问题,我感到有点“火爆”。
一些背景
Ye olde(10.4 之前)FreeAndNil看起来像这样:
FreeAndNil(var SomeObject)
Run Code Online (Sandbox Code Playgroud)
新的和新鲜的FreeAndNil看起来是这样的:
FreeAndNil(const [ref] SomeObject: TObject);
Run Code Online (Sandbox Code Playgroud)
IMO 都有其缺点:
FreeAndNil指针、记录和接口编译得很好,但在运行时会产生有趣但通常不需要的效果。(完全狂暴,或者如果幸运的话它会因 EAccessViolation、EInvalidOperation 等而停止。)FreeAndNil像这样调用新的:FreeAndNil(TObject.Create)它会编译甚至运行得很好。我喜欢FreeAndNil在我出错时警告我并提供例如属性而不是字段的旧版本。不确定如果为此FreeAndNil实现提供对象类型属性会发生什么。没试。如果我们将签名更改为 ,FreeAndNil(var SomeObject:TObject)那么它将不允许我们传递任何其他变量类型,然后正是该TObject类型。这也是有道理的,好像不是这样FreeAndNil,人们可以轻松地更改TComponent在例程中作为类型提供的变量,将 var 变量更改为完全不同类型的对象,例如TCollection. 当然FreeAndNil不会做这样的事情,因为它总是将 var 参数更改为 nil。
所以这是FreeAndNil一个特例。
甚至可能特别到足以说服 delphi 添加一个编译器魔术 FreeAndNil实现?投票给任何人?
潜在的解决方法 …
delphi memory-management object-lifetime rad-studio delphi-run-time-library
我怀疑FreeAndNil是否是处理对象的理想方法.我遇到过类似的代码
StringList1.Free;
StringList1 := Nil;
Run Code Online (Sandbox Code Playgroud)
用来.上述行是否过度,或者是更好的做事方式?这两种方法有什么区别?
我在下面的代码中为用户类显示了一个简短的设计模式.
type
MytestClass = class
alist: TStringlist;
public
constructor Create;
destructor destroy; override;
end;
{ MytestClass }
type
TForm1 = class(TForm)
btn_version01: TBitBtn;
btnversion02: TBitBtn;
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure FormCreate(Sender: TObject);
procedure btn_version01Click(Sender: TObject);
procedure btnversion02Click(Sender: TObject);
private
{ Private-Deklarationen }
public
{ Public-Deklarationen }
btestClass : MytestClass;
aComplexClassDesign : TComplexClassDesign;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
constructor MytestClass.Create;
begin
alist := TStringlist.Create;
end;
destructor MytestClass.destroy;
begin
alist.free;
inherited;
end;
procedure TForm1.btnversion02Click(Sender: TObject);
var atestClass : …Run Code Online (Sandbox Code Playgroud)