怎样判断一个指针是否指向的是一个对象(50分)

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

amber

Unregistered / Unconfirmed
GUEST, unregistred user!
程序中p:Pointer为一个可能指向对象(TObject)或结构(record)的指针,现在需要判断该指针到底是
指向对象,还是结构,物品的思路是这样的
注意:THostManage是一个对象类型
try
if (TObject(p) is THostManage) then
begin
// 该对象是THostManage
end
else
begin
// 该指针指向一个对象
end;
except
// 该指针指向是一个结构
end;
这样好象可以判断,但有时候会引起系统其他部分的故障,造成其他部分访问冲突,敢问大虾
们,有没有更直接的办法判断指针指向的数据类型啊

 
能得到吗?怀疑/
 
1: 判断p是否为空
2:用 TObject(p) is TObject判断P是否为对象
3:否则为结构
 
我觉得是没有办法确定的,最直接的办法就是由使用你过程的调用者告诉你他传进来的是
对象还是记录.可以使用 overload 定义你的函数,如:
procedure YourProc(param: THostManager);overload;
begin
...
end;
procedure YourProc(param: TYourRecord);overload;
begin
...
end;
或者参数是指针,外加一个附加参数说明指针指向的是对象还是记录.如:
type
TParamType = (ptObject, ptRecord);

procedure YourProc(param: Pointer
ParamType: TParamType);
begin
if Param = nil then exit;
if (ParamType = ptObject) then
with THostManager(Param) do ...
else
with TYourRecord(Param^) do ...
end;
 
无法准确得到你所需要的数据类型!

Pointer 是一个无类型指针,可以指向任何元素。
转化时,Delphi 并不知道 Pointer 指向的数据
是什么类型,实际上,TObject(p) 是一种强制转换,
也就是说:编译器不能确定类型转换的正确性!
你必须自己负责该指针的实际指向!

虽然用 is 运算可以作一些判断,也有可能在有穷
序列中找到相符的数据 ---------- 但这是很偶然的,
没有事实的确定依据。
比如:一个父类 Parent, 一个子类 Child.判断时,
child is parent 是对的;但 parent is child 就是
错的。(Child as Parent).Parent_Method() 肯定不会
出现问题;(Parent as Child).Child_Method() 则必然
会出错。


总得说来,无类型指针的转换是没有安全性的,
你必须明确指针对象才可以得到真正的确定对象。
 
根本不可能。
 
道理很简单,我举一个例子:

任何对象、结构、变量什么的,在内存里面,实质上就是字节流,那么很有可能某一个
字节数组array of char的内容刚好和某一个对象的字节流内容一样,如果一个pointer
指向的内容为上述字节内容,你能区分是那个对象还是array of char的字节数组?


指针就是一个指针而已,指向一个内存地址,该地址内容的解释需要你自己来完成,是
整型?是浮点型?是4字节数组?随你便,但是别来问我。 ---- 计算机
 
>可能指向对象(TObject)或结构(record)
真的需要这样做吗?
如一个过客所说,事实上并没有绝对安全的方法。
是否可以通过将Record封装为Object或者通过另外一个参数表明Pointer的身份?
 
实在不行,就用try...except...end
哈哈哈
 
同意一个过客
 
你在玩花样吗?
 
我也认为不可能,看一下,CSDN上,
OB的对象指针的讨论,对你可能有
帮助。不只是,用TPOINTER
用别的也,很难实现。因为,一个
整型的指针,也可以,当成
对象的指针用。CSDN上有帖子。
注意NICROSOFT的话。
 
何处结束呀?
 
以前不是讨论过吗?

http://www.delphibbs.com/delphibbs/dispq.asp?lid=839586

来自:flier, 时间:2002-1-23 20:40:00, ID:880371 | 编辑
首先,建议你修改你的设计,因为这种参数的模糊性很容易造成错误的发生
其次,实现你的要求,需要用到Delphi VTable的信息,因为判定一个
地址是否指向有效对象的一个重要依据就是这个地址是否指向一个有效的VMT
而此VMT中有很多可供判定的数据,我这里使用的是vmtSelfPtr,一个保存
在VMT中的Self指针,应该可以排除掉绝大多数随机情况,但如果此片内存
刚刚被一个对象使用,则无法判定。因此判定是无法做到100%的,最好修改设计
function IsValidObject(const Obj: TObject): Boolean;
begin
try
Result := PInteger(Integer(Obj.ClassType)+vmtSelfPtr)^ = Integer(Obj.ClassType);
except
Result := False;
end;
end;
注意这里用一个try...except把代码控制起来,因为无效地址传入可能引起
无效内存访问异常。

下面是JCL里面的实现方法,思路类似

function IsClass(Address: Pointer): Boolean
assembler;
asm
CMP Address, Address.vmtSelfPtr
JNZ @False
MOV Result, True
JMP @Exit
@False:
MOV Result, False
@Exit:
end;

//--------------------------------------------------------------------------------------------------

function IsObject(Address: Pointer): Boolean
assembler;
asm
// or IsClass(Pointer(Address^));
MOV EAX, [Address]
CMP EAX, EAX.vmtSelfPtr
JNZ @False
MOV Result, True
JMP @Exit
@False:
MOV Result, False
@Exit:
end;
 
后退
顶部