我为整型变量分配对象和整数值:如何检查对象是否被分配到一个整数变量
MyIntegerValue := Integer(MyObject);
MyIntegerValue := 2;
MyIntegerValue := 500;
...
如何检查是否MyIntegerValue已经分配了一个有效的对象?
我为整型变量分配对象和整数值:如何检查对象是否被分配到一个整数变量
MyIntegerValue := Integer(MyObject);
MyIntegerValue := 2;
MyIntegerValue := 500;
...
如何检查是否MyIntegerValue已经分配了一个有效的对象?
如何检查MyIntegerValue是否已分配有效对象?
你不行。没有数据位来指示Integer
正在持有什么。一个指针(不管它指向什么)只是一个数字,就CPU而言。它恰好是代表内存地址的数字。
此外,您尝试一个对象指针存储在一个Integer
不会在64位系统的工作,你就需要使用NativeInt
/NativeUInt
代替,否则你将截断指针值。
要做你在问什么,你将不得不使用另一个变量来表示Integer
值代表什么。或者更好的是,使用知道它所持有的容器类型,如TValue
或Variant
(是的,您可以将对象指针存储在Variant
中,但有一些工作)。
你无法可靠地做到这一点,你不应该试图在德尔福智胜型安全。
澄清:凭借可靠的我指的是以下情况:
您赋给变量的整数。然后,稍后您回来并想确定它是整数还是对象引用。您可能会试图通过调查指向的内存块来检查它是否为对象引用。您可能会看到结构和数据显示为Free Consulting
。阿哈,你想,我已经存储了一个对象引用!但是,实际上您确实存储了一个整数,它的值恰好与对象的地址一致。
和
您指定一个有效对象引用,后来该对象被释放,而内存是什么重用。您检查内存结构等对象失败,并得出错误的结论,即您存储了整数。
自从very first comment向您提问以外,您应该关注有关类型安全性和类型转换的内容。我不会重复这一点,并专注于具体问题的实际方法。这也将讨论限制在32位目标上(因为你的问题假设为SizeOf(Integer) = SizeOf(Pointer)
);
首先,因为对象是指针(当你从对方回复得知),其平台强加的特性可以帮助真正的指针(有效!)和整数值来区分。看看Windows如何告诉字符指针和列举值之外:
function Is_IntResource(lpszType: PChar): BOOL;
begin
Result := ULONG_PTR(lpszType) shr 16 = 0;
end;
这利用了什么没有用户模式数据可以在低内存区域在32位Windows平台上进行分配,并因此事实,不存在有效的指针值p < 65536
。
接下来,可以使用对象的实例的Delphi专用内部数据格式,以检查是否指针是一个真正的对象实例:
/// <summary>
/// Verifies that the argument points to valid object instance.
/// </summary>
/// <exception cref="EAccessViolation">
/// If segmentation fault occurs while attempting to read VMT and/or its
/// field from the specified memory address.
/// </exception>
/// <remarks>
/// Delphi only, incompatible with FPC.
/// </remarks>
/// <example>
/// <code lang="Delphi">
/// procedure TForm1.FormCreate(Sender: TObject);
/// begin
/// ShowMessage(BoolToStr(IsInstance(Self), True));
/// end;
/// </code>
/// </example>
function IsInstance(Data: Pointer): Boolean;
var
VMT: Pointer;
begin
VMT := PPointer(Data)^;
Result := PPointer(PByte(VMT) + vmtSelfPtr)^ = VMT;
end;
此功能检查V irtual 中号 ethod Ť能够用于Delphi RTL的签名和(给定内存读取操作成功并且签名检查通过)将任意指针标识为TObject
(或后代)实例。
nil
/0
:你需要花约0
指针值一个更加特殊的预防措施,因为它是作为Pointer
非常有意义的,也是常见的Integer
。
此外,IIRC 32位Windows在地址空间的顶部还保留了内存区域,这意味着也可以识别小的负值。 –
+1 [内部数据格式(德尔福) - 类类型](http://docwiki.embarcadero.com/RADStudio/Seattle/en/Internal_Data_Formats#Class_Types)用于VMT引用 - 请参阅'vmtSelfPtr'常量 – fantaghirocco
[TValue](http://docwiki.embarcadero.com/Libraries/en/System.Rtti.TValue)可以同时存放整数类型和类实例。没有安全的方式来说你的整数指向一个实例化的类。 –
最简单的方法是**不要那么做**,因为这很愚蠢。不要混合整数和对象,并且你没有这个问题。严重的是,当你开始不得不提出这样的问题时,这是一个非常强烈的迹象表明你已经做了一件完全错误的事情,而摆脱这种情况的最好方式就是停止做那样做的事情,那样做是错误的,以至于你不得不问这个问题。 –