Jas*_*mis 2 delphi memory-management interface access-violation
我正在努力学习来自C#的delphi和内存管理.
目前这种斗争的化身是,当我完成它们时,我不知道处理物体的正确方法.从阅读和我的实验看来,如果我有一个被转换为接口的对象,那么我的唯一选择是将引用设置为nil.如果我去打电话FreeAndNil()我最终得到一个访问冲突,EX:
var
foo: IFoo;
begin
foo := TFoo.Create();
FreeandNil(foo);
end;
Run Code Online (Sandbox Code Playgroud)
当然,我需要做的就是改变那个foo:IFoo; foo:TFoo; 它很开心 或者只是将指针设置为nil,而不是调用freeandNil.
foo := nil;
Run Code Online (Sandbox Code Playgroud)
所以,在一个层面上,我至少不了解AV的位置.
在不同的层面上,我想编写代码,使得它不需要知道它是接口还是对象.我希望能够以同样的方式编写所有内存管理,但我似乎无法编写一个可以处理类或接口的方法.嗯,这不是真的,我确实有一些东西,但它是如此丑陋,我犹豫发布它.
但我想我也应该问,其他人在做什么?精神上跟踪什么是界面,只是那些指针?否则调用FreeAndNil?
我想要第一次实现作为具体类的东西,但后来回来并将其更改为接口,当我找到代码可以通过两种不同方式进行操作时.而且我不打算通过代码来改变处理该引用的方式,这是我当时最后的想法.
但是为了讨论,我最好的(几乎是唯一的)想法就是这个课程:
interface
type
TMemory = class(TObject)
class procedure Free(item: TObject); overload; static;
class procedure Free<T: IInterface>(item: T); overload; static;
end;
implementation
uses
System.SysUtils;
{ TMemory }
class procedure TMemory.Free(item: TObject);
begin
FreeandNil(item);
end;
class procedure TMemory.Free<T>(item: T);
begin
//don't do anything, it is up the caller to always nil after calling.
end;
Run Code Online (Sandbox Code Playgroud)
然后我可以一直打电话:
TMemory.Free(Thing);
Thing := nil;
Run Code Online (Sandbox Code Playgroud)
测试代码:
procedure TDoSomething.MyWorker;
var
foo: IFoo;
fooAsClass: TFoo;
JustAnObject: TObject;
begin
foo := TFoo.Create();
fooAsClass := TFoo.Create();
JustAnObject := TObject.Create();
TMemory.Free(foo);
foo := nil;
TMemory.Free(fooAsClass);
fooAsClass := nil;
TMemory.Free(JustAnObject);
JustAnObject := nil;
end;
Run Code Online (Sandbox Code Playgroud)
运行时没有泄漏或访问冲突.(使用MadExcept)
但非常感谢德尔福社区的SO.你们这是学习中最好的东西!
访问冲突的原因是FreeAndNil采用无类型参数,但期望它是一个对象.因此该方法对该对象进行操作.
procedure FreeAndNil(var Obj);
var
Temp: TObject;
begin
Temp := TObject(Obj); //Obj must be a TObject otherwise all bets are off
Pointer(Obj) := nil; //Will throw an AV if memory violation is detected
Temp.Free; //Will throw an AV if memory violation is detected
end;
Run Code Online (Sandbox Code Playgroud)
内存违反上述威力(NB不能保证),如果您销毁或者已被毁坏之前或从未创建的对象进行检测.它也可能被检测到,如果Obj根本没有引用一个对象而是其他东西(例如接口,记录,整数,因为它们没有实现Free,如果它们没有实现,它将不会以相同的方式定位TObject.Free) .
在不同的层面上,我想编写代码,使得它不需要知道它是接口还是对象.我希望能够以同样的方式编写所有内存管理.
这就像是说你想要使用你的汽车,就像你使用淋浴一样.
好吧,也许差异不是那么极端.但关键是接口和对象(以及对于那个事件记录)使用不同的内存管理范例.你无法以同样的方式管理他们的记忆.
| 归档时间: |
|
| 查看次数: |
788 次 |
| 最近记录: |