这里的观察者实现是否有内存泄漏?

non*_*one 3 delphi memory-leaks design-patterns

也许我不太了解德尔福,但是我想问你:

在这个网站:http://blogs.teamb.com/joannacarter/2004/06/30/690我发现了一个基于iterface的观察者模式的实现.

在做附件时,有一个调用:

procedure TSubject.Attach(Observer: IObserver);
begin
    if fObservers = nil then
      fObservers := TInterfaceList.Create;
    fObservers.Add(AObserver);
    Notify;
end;
Run Code Online (Sandbox Code Playgroud)

在分离中它有代码

procedure TSubject.Detach(Observer: IObserver);
begin
   if fObservers <> nil then
    begin
      fObservers.Remove(AObserver);
      if fObservers.Count = 0 then
        fObservers := nil;
    end;
end;
Run Code Online (Sandbox Code Playgroud)

它应该是:

procedure TSubject.Detach(Observer: IObserver);
begin
   if fObservers <> nil then
    begin
      fObservers.Remove(AObserver);
      if fObservers.Count = 0 then begin
        fObservers.Free; 
        fObservers := nil;
      end;
    end;
end;
Run Code Online (Sandbox Code Playgroud)

him*_*elf 6

不,它不应该,因为正如巴拉特所说,IInterface将负责这一点.请注意,在您遇到的示例中,fObservers被声明为IInterfaceList.这是一个界面.Delphi中的接口变量类似于C++中的智能指针,它们在赋值时自动调用_Addref和_Release.

另一方面,如果fObservers被声明为TInterfaceList,那么它将是一个对象,并且对象在赋值时不做任何特殊操作,因此调用Free是正确的.

  • 如果fObservers被声明为TInterfaceList*,则备注+1. (2认同)

Bha*_*rat 5

没有必要添加fObservers.Free;语句.IInterface将负责添加和释放fObservers.

Delphi用于_AddRef and _Release管理接口对象的生命周期.

当您为接口变量分配接口引用时,Delphi会自动调用_AddRef.

当变量超出范围时,Delphi会自动调用_Release.

欲了解更多信息,请浏览此链接.

  • @none:两个原因:因为它不是垃圾收集,而是引用计数,就像COM和其他实现COM之类的接口的语言一样.Delphi对象模型比Delphi接口实现更旧(在引入ActiveX后,COM非常流行,后者是Delphi 1和2).Delphi团队无法承担从头开始重写VCL/RTL以完全基于接口的方式(就像微软从未出于同样的原因那样使用MFC).此外,引用计数还存在垃圾收集不具备的问题.问一个新问题. (3认同)
  • Delphi不是一种完整的垃圾收集语言,应手动分配和取消分配用户定义的类型.它仅为少数内置类型提供自动收集,例如字符串,动态数组和界面,以便于使用. (2认同)
  • @none你可以通过自由使用接口获得类似垃圾收集的结果.这意味着所有的类都需要实现至少一个接口:`TMyClass = A类(TInterfacedObject,IMyInterface的)`...,所有引用应该是接口引用:`为MyObject:IMyInterface`.请注意,循环引用可能会导致引用计数出现问题. (2认同)