200分,你能解决吗?interface接口循环引用计数-无法释放(200分)

  • 主题发起人 主题发起人 LoveKilly
  • 开始时间 开始时间
L

LoveKilly

Unregistered / Unconfirmed
GUEST, unregistred user!
interface IProject
property Windows;
end;

interface IWindows
property Items[Item: OleVariant];
procedure Append(...);
procedure Remove(...);
end;

interface IWindow
property Windows: IWindows;
property Name: string;
...
end;
 
你就贴这个让人家看什么啊?晕头。
接口就是接口了,无论使用什么接口,都需要使用接口类进行实现,只要从TInterfaceObject继承下来,接口都能够很好的释放。
 
unit uIntfClass;
interface
windows,intfunit(你的上面的接口);
type
TMyIntfClass=Class(TinterfacedObject,IWindows,IWindow,IProject)
private
public
.....
end;
 
to 蓝叶菱:
蓝兄误解我意也!IWindows接口在IProject构造函数中创建,且它引用了IProject接口,IProject同时也引用了IWindows,这就是接口循环引用!IWindows释放时等待IProject接口释放,而IProject接口亦等待IWindows接口释放,你可以用三个TInterfacedObject类来分别实现这个三接口,然后在析构函数添加断点监视,看看能否正确执行。呵呵,谢谢啦。
 
代码不是delphi的,也不是java的. 你是表达意思吧.
我就不明白了, 为什么在接口中声明属性??

我认为接口的属性功能是对接口的污染.. 郁闷...
 
要是那样,可以使用接口实现啊。干什么循环引用。
f:implemation Fwindows:
end;
 
上面的代码只是一种示意,实际上我是使用Delphi开发的。
假设,我们要用接口模拟实现窗体和控件,那么,有如下三个接口定义:
IForm,IControls,IControl
跟上面讲的一样,实现起来会出现循环引用,导致有的接口无法释放,有时间的话,各位可以试试!
 
用java 或者 .net吧,否则没法解决.
 
to xeen:
xeen兄可否详解其中原因: >> 用java 或者 .net吧,否则没法解决.
 
各位,我现在开发矢量图形引擎,内部实现全部使用接口,请有使用接口编程的高手提供宝贵的意见,小的感激不尽,呵呵。
 
修改实现接口的类的_Release方法,只让它减少接口引用计数而不要让它干涉对象生命周期
function TXX._Release: Integer
begin
Result := InterlockDecrement(FRefCount);
//if Result := 0 then
// Destroy;
end;
 
看这个:
Pointer -----> A ------>B
↑ |
| ↓
|________ C
局部变量 Pointer 指向A, A、B、C组成了一个环行结构存在于堆中。
很明显A的引用记数为2,B和C则为1.
这时候执行: Pointer := nil;会怎么样?
A的引用记数为1,不会释放,B,C也不会释放。这三个对象就内存泄露了.

解决此类方法的万全之策就是使用java或者.net,GC替你帮忙。程序员自己成天
想着怎样释放/分配内存是很累的。
 
关键是IWindows,为它增加一个状态即可,比如delete_flg:boolean;在其初始值为false;当释放时,如果发现为true则exit,否则
首先让delete_flg为true,然后进行释放动作。这样不会循环释放的!

.net自动回收时,framework能够知道那个对象已经被释放和正在释放,不会重复释放和循环释放,但delphi一样能解决。
java,不懂!
 
多谢各位!最后解决如下:

type
TInterfaceState = (isDestroying, isDestroyed);
TInterfaceStates = set of TInterfaceState;

INoneRefInterface = interface(IInterface)
['{3C606524-716A-4198-B5B6-B2637AB16216}']
procedure FreeNotifation; stdcall;
end;

TWindows = class(TInterfacedObject, IInterface, INoneRefInterface)
private
FInterfaceStates: TInterfaceStates;
protected
// Interface IInterface implement
function _AddRef: Integer; stdcall;
function _Release: Integer; stdcall;

// Interface INoneRefInterface implement
procedure FreeNotifation; stdcall;
public
constructor Create(...);
destructor Destroy; override;
end;

implementation

constructor TWindows.Create(...);
begin
inherited ;
FInterfaceStates := [];
// ...
end;

destructor TWindows.Destroy;
begin
Exclude(FInterfaceStates, isDestroying);
Include(FInterfaceStates, isDestroyed);

// ...
inherited ;
end;

function TWindows._AddRef: Integer;
begin
Result := 1;
end;

function TWindows._Release: Integer;
begin
if isDestroying in FInterfaceStates then
begin
Result := 0;
Free;
end
else if isDestroyed in FInterfaceStates then
Result := 0
else
Result := 1;
end;

procedure TWindows.FreeNotifation;
begin
Include(FInterfaceStates, isDestroying);
end;

// 使用时
var Windows: IWindows;
begin
Windows := CoWindows.Create(...);
Windows.Append(...);
Windows.Append(...);
(Windows as INoneRefInterface).FreeNotifation; // 真正需要释放对象时
// 否则只需将其赋为nil,_Release一下就可以了
Windows := nil;
end;
 
只是,还有些问题,现无法查出其它部分到底哪里没有释放,我用的是FastMM4.pas,不过还是多谢各位啦。
呵呵,感觉这趟没有白来,一下子来了这么多高手,有些舍不得结束哦,我是初次完全在项目中使用接口,感觉很接口编程好处多多,用起来还是无法像用纯类那样地得心应手(上一版本就是纯类的,新的版本全部用接口)。我现在开发矢量图形引擎,目前有两三万行的代码了,光是这个引擎,呵呵,不知各位有何建议,在此多谢啦。
 
楼上的 老大 能不能给点接口编程的建议,对这个不很了解??或者留下qq号
 
to 52free:
  我采用了你提的方法,在适当的时候调用一个特殊的函数使接口释放,在这之后,可能还有对该接口的_Release方法调用,运行产生不可预料的错误。
  比如像这种:
destrucotr TX.Destroy;
begin
FWindows := nil;
// Deiphi 编译器默认会在这里 添加对_Release的调用,在这之前,该接口已被释放!!!
   FWindows._Release;
end;
 
to xeen:
.NET平台的确可以帮助程序员自动处理很多的细节,像内存自动回收就是一个很好的例子,对于我来说,进军.NET是很遥远的事情,况且,公司不可能也不允许在花了大量时间、大量精力构建好的项目再重新使用.NET开发。
  xeen兄多帮帮忙,问题一定可以解决的,Delphi的Open Tools API也是使用接口开发的,难道他们就不会遇到接口循环引用的问题?
 
感觉你的接口设计是否有一些问题,你的接口之间的耦合度是否太高,如果使用接口出现循环引用,应该是设计的问题,不应该把问题重点放在引用释放上,正常的逻辑是不应该出现循环引用的。
 
to appfirst:
appfirst兄能否给些建议,到底我的接口哪个部分设计地有问题,应该怎么改进?
 
后退
顶部