如何检查对象是否已分配给整数变量

时间:2016-02-04 22:14:43

标签: delphi casting variable-assignment

我将对象和整数值分配给整数变量:

MyIntegerValue := Integer(MyObject);
MyIntegerValue := 2;
MyIntegerValue := 500;
...

如何检查MyIntegerValue是否已分配有效对象?

3 个答案:

答案 0 :(得分:8)

  

如何检查MyIntegerValue是否已分配有效对象?

你做不到。没有数据位来指示Integer持有的内容。指针(无论它指向什么)只是一个数字,就CPU而言。它恰好是一个代表内存地址的数字。

此外,您在Integer中存储对象指针的尝试在64位系统上无效,您需要使用NativeInt / NativeUInt,否则会截断指针值。

要执行您要求的操作,您必须使用另一个变量来指示Integer值表示的内容。或者更好的是,使用一个容器类型,知道它持有什么,比如TValueVariant(是的,您可以将对象指针存储在Variant中,但有些工作)。

答案 1 :(得分:4)

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;

此功能检查能够进行Delphi RTL签名的 V irtual M ethod T (给定内存读取操作成功并通过签名检查) )将任意指针标识为TObject(或后代)实例。

nil / 0:您需要对0指针值采取更加特殊的预防措施,因为它与Pointer非常有意义,并且与{{{{{{ 1}}。

答案 2 :(得分:1)

你无法可靠地做到这一点,你不应该试图超越德尔福的类型安全。

澄清:可靠我的意思是以下情况:

为变量指定整数。然后,稍后您回来并想确定它是整数还是对象引用。您可能想通过调查指向的内存块来首先检查它是否是对象引用。您可能会看到Free Consulting显示的结构和数据。 Ahaa,你想,我已经存储了一个对象参考!但是,实际上你确实存储了一个整数,它的值恰好与一个对象的地址重合。

您指定了一个有效的对象引用,稍后释放该对象并重新使用该内存。检查内存结构等对象是否失败,并得出错误的结论,即存储了一个整数。