简体   繁体   English

检查空闲对象实例

[英]Check free object instance

I have the following class structure. 我有以下课程结构。

TObjectA = class
    ...
end;

TObjectB = class
    private
        FDependencyObjectA
    public
        constructor Create(const DependencyA: TObjectA);
        destructor Destroy; override;
end;

{ TObjectB }

constructor TObjectB.Create(const DependencyA: TObjectA);
begin
    FDependencyObjectA := DependencyA;
end;

destructor TObjectB.Destroy;
begin
  FDependencyObjectA.Free;
  FDependencyObjectA := nil; 
  inherited;
end;

I'm trying to find a solution to work with these two use cases. 我正在尝试找到一种可用于这两个用例的解决方案。

// Use cases

// First case 
// Works with Free on Destroyer
// Does not work without Free on Destroyer
procedure TForm1.Button1Click(Sender: TObject);
var
 ObjectB: TObjectB;
begin
   ObjectB := TObjectB.Create(TObjectA.Create);
   try
       ...
   finally
       ObjectB.Free; 
   end;
end;


// Second case
// Does not work with Free on Destroyer
// Works without Free on Destroyer
procedure TForm1.Button1Click(Sender: TObject);
var
 ObjectA: TObjectA;
 ObjectB: TObjectB;
begin
   ObjectA := TObjectA.Create;
   ObjectB := TObjectB.Create(ObjectA);
   try
       ...
   finally
       // Depending on the implementation of the Destroyer or the this finally
       // Can raise Access Violation, Invalid Pointer or Memory Leak
       ObjectB.Free; 
       ObjectA.Free;
   end;
end;

One solution would be to verify that ObjectA has already been free of memory. 一种解决方案是验证ObjectA已经没有内存了。 But I do not know a check only when the object is free, I know checks of when the object is null. 但是我不知道只有在对象空闲时才进行检查,我知道对对象何时为空进行检查。

// Third case (Trying for a solution)
procedure TForm1.Button1Click(Sender: TObject);
var
 ObjectA: TObjectA;
 ObjectB: TObjectB;
begin
   ObjectA := TObjectA.Create;
   ObjectB := TObjectB.Create(ObjectA);
   try
       ...
   finally
       ObjectB.Free;       
       // It would work fine if Assigned returned false, but always returns true
       if Assigned(ObjectA) then  // or ObjectA <> nil
         ObjectA.Free;
         // If I use just assign nil instead of Free, compile throws a hint
         // ObjectA := nil;
         // H2077 Value assigned to 'Your_Variable' never used
   end;
end;

Another solution would be to inject the dependency using the reserved word var. 另一种解决方案是使用保留字var注入依赖项。 But I want to evaluate other possibilities first. 但是我想首先评估其他可能性。

In Delphi is there any way to check if the object is just free and not only nil? 在Delphi中,有什么方法可以检查对象是否只是自由对象,而不仅仅是nil?

Or is there any workaround to work with the first two use cases, without Access Violation, Invalid Pointer, Memory Leak or Compile Hints errors? 还是在前两个用例中有任何变通办法,而没有访问冲突,无效指针,内存泄漏或编译提示错误?

I did not just want to adopt just one use case, or have to keep checking the object's Destroyer to know how to implement a new function / procedure. 我不只是想采用一个用例,也不是要不断检查对象的Destroyer以了解如何实现新的功能/过程。 This is bad for day-to-day implementations, or for when a new developer gets into the project. 这对于日常实施或新开发人员进入项目时都是不利的。 We would have to explain all these little rules and also be constantly reviewing whether the implementations are correct. 我们将不得不解释所有这些小规则,并且还要不断地审查实现是否正确。

Edit: 编辑:

I know that Delphi has ARC for Interfaces, but not all objects will implement an interface. 我知道Delphi具有用于接口的ARC,但并非所有对象都将实现接口。

For hints there is the {$ Hints Off} compilation directive, but in any case adding the directive is not very viable. 对于提示,有{$ Hints Off}编译指令,但是无论如何添加该指令不是很可行。

The correct code is this: 正确的代码是这样的:

ObjectA := TObjectA.Create;
ObjectB := TObjectB.Create(ObjectA);
try
  ...
finally
  ObjectB.Free;       
end;

ObjectB takes ownership of ObjectA and it is therefore its job to destroy it. ObjectB拥有ObjectA所有权,因此销毁它是它的工作。 The calling code has passed on that responsibility and so has nothing more to do. 调用代码已经承担了该责任,因此无需执行其他任何操作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM