异想天开:在类方法中如何得知自身的实例已经被其他线程或过程释放掉了。(200分)

  • 主题发起人 主题发起人 Another_eYes
  • 开始时间 开始时间
A

Another_eYes

Unregistered / Unconfirmed
GUEST, unregistred user!
除了try...except...end之外是否有可能在类的方法中得知自身已经被其他线程或过程释放掉了。
我尝试过用IsBadReadPtr/IsBadWritePtr(pointer(self), TXXXX.InstanceSize)来判断,结果失败了,该死的IsBadReadPtr/IsBadWritePtr总是返回false,但接着的操作肯定又触发一个Access violation异常。
 
类方法?得知自身?
自身到底指谁?
 
老問題!
---->引用計數.
 
类方法? or 对象方法?
前者:需另讨论
后者:已有讨论 http://www.delphibbs.com/delphibbs/dispq.asp?lid=1556758

 
在Aimingoo主页《如何跨单元、跨类地访问Delphi 类的私有域方法》
那里有个函数,是取堆指针长度的,而我们所用的对象也是一个指针,所以,可以用它来判断,如下:

/// <summary>
/// 得到堆指针的指针长度,如一个对象或动态得到的指针
/// 如:
/// if : GetMem(P, 10);
/// then: Len := GetPtrSize(P) ==> 10
///
/// if : Obj := TObject.Create;
/// then: Len := GetPtrSize(Obj) ==> Obj.InstanceSize;
/// if : Obj.Free;
/// then: Len := GetPtrSize(Obj) ==> 0;
///
/// 不能是栈指针的指针,如临时、局部变量的取地址得到的指针
/// </summary>

function GetPtrSize(P: PChar): Integer;
const
cThisUsedFlag = 2;
cPrevFreeFlag = 1;
cFillerFlag = Integer($80000000);
cFlags = cThisUsedFlag or cPrevFreeFlag or cFillerFlag;
type
PUsed = ^TUsed;
TUsed = packed record
sizeFlags: Integer;
end;
begin
Result := 0;
Dec(P, sizeof(TUsed));
if (PUsed(P).sizeFlags and cThisUsedFlag) <> 0 then
begin
Result := PUsed(P).sizeFlags and not cFlags;
if (PUsed(P).sizeFlags and cFillerFlag) = 0 then //取实际长度
Dec(Result, sizeof(TUsed));
end;
end;

Call:
if GetPtrSize(Pointer(Self)) = 0 then
raise Exception.Create('Self is invalid');
 
小弟不是很懂,不过冒昧试想一下:
不知Delphi里面(或API里面)是否有读取内存的函数?如果有,这个函数是否能判断内存字节是否在进程内部?(应该可以吧,ring3的程序不能读进程外的内存吧?)如果我的假设成立,那么首先拿到对象指针(Self应该是这个指针吧),然后用读取内存的函数读指针指向的地址,如果这个地址里面有什么信息(我也不知道是什么信息)能够表明实例存在,内存访问可以成功,那么就判断实例没有被消除;否则,就表示实例已经被清除了,内存也被锁定了,需要重新分配才能读取。

小弟冒昧之言,可能错误百出,呵呵,请大虾不要笑话,如果可能,也请大家指正。
 
实例被消除,又哪来的self指针?
判断自身的引用计数是个经典问题,com的相关论述中可以看到这方面讨论
 
可以。
只要覆盖了虚方法procedure FreeInstance
virtual;就行了
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
D
回复
0
查看
2K
DelphiTeacher的专栏
D
后退
顶部