Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi 如何检查对象是否已分配给整数变量_Delphi_Casting_Variable Assignment - Fatal编程技术网

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

Delphi 如何检查对象是否已分配给整数变量,delphi,casting,variable-assignment,Delphi,Casting,Variable Assignment,我将对象和整数值都分配给一个整数变量: MyIntegerValue := Integer(MyObject); MyIntegerValue := 2; MyIntegerValue := 500; ... 如何检查MyIntegerValue是否被分配了有效的对象?您无法可靠地执行此操作,并且不应试图在Delphi中胜过类型安全性 澄清一下:我指的是以下情况: 为变量指定一个整数。然后,稍后返回并确定它是整数还是对象引用。您可能会首先通过调查指向的内存块来检查它是否是对象引用。您可能会看到

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

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

如何检查MyIntegerValue是否被分配了有效的对象?

您无法可靠地执行此操作,并且不应试图在Delphi中胜过类型安全性

澄清一下:我指的是以下情况:

为变量指定一个整数。然后,稍后返回并确定它是整数还是对象引用。您可能会首先通过调查指向的内存块来检查它是否是对象引用。您可能会看到免费咨询显示的结构和数据。啊哈,你认为,我存储了一个对象引用!然而,您实际上存储了一个整数,它的值恰好与对象的地址一致


您分配了一个有效的对象引用,之后该对象将被释放,内存将被重用。检查对象(如内存结构)失败,并得出错误的结论,即您存储了一个整数。

您无法可靠地执行此操作,并且不应试图在Delphi中智取类型安全性

澄清一下:我指的是以下情况:

为变量指定一个整数。然后,稍后返回并确定它是整数还是对象引用。您可能会首先通过调查指向的内存块来检查它是否是对象引用。您可能会看到免费咨询显示的结构和数据。啊哈,你认为,我存储了一个对象引用!然而,您实际上存储了一个整数,它的值恰好与对象的地址一致

您分配了一个有效的对象引用,之后该对象将被释放,内存将被重用。对类似对象的内存结构的检查失败,并得出错误结论,即存储了一个整数

如何检查MyIntegerValue是否分配了有效的对象

你不能。没有数据位指示整数所包含的内容。就CPU而言,指针无论指向什么,都只是一个数字。它恰好是一个表示内存地址的数字

此外,尝试将对象指针存储在整数中不会在64位系统上工作,您需要使用NativeInt/NativeUInt,否则将截断指针值

要执行要求的操作,必须使用另一个变量来指示整数值代表的内容。或者更好的方法是,使用一个知道它包含什么的容器类型,比如TValue或Variant,是的,您可以通过一些工作将对象指针存储在Variant中

如何检查MyIntegerValue是否分配了有效的对象

你不能。没有数据位指示整数所包含的内容。就CPU而言,指针无论指向什么,都只是一个数字。它恰好是一个表示内存地址的数字

此外,尝试将对象指针存储在整数中不会在64位系统上工作,您需要使用NativeInt/NativeUInt,否则将截断指针值


要执行要求的操作,必须使用另一个变量来指示整数值代表的内容。或者更好的方法是,使用一个知道它所包含的内容的容器类型,比如TValue或Variant。是的,您可以通过一些工作将对象指针存储在一个Variant中。

您应该注意自问题出现以来有关类型安全和类型转换的内容。我将不再重复这一点,而将重点放在解决具体问题的实际方法上。这也将讨论限制为32位目标,因为您假设SizeOfInteger=SizeOfPointer

首先,由于对象是指针,正如您从其他回复中了解到的,它的平台强制属性有助于区分真正的指针和有效的指针!和整数值。看看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的虚拟方法表的签名,并在给定内存读取操作成功且签名检查通过后将任意指针标识为对象或子实例


nil/0:对于0指针值,您需要采取更为特殊的预防措施,因为它作为指针非常有意义,作为整数也很常见。

您应该注意自从向您提出问题以来关于类型安全和类型转换的内容。我将不再重复这一点,而将重点放在解决具体问题的实际方法上。这也限制了t 当您提问时,对32位目标的讨论假设SizeOfInteger=SizeOfPointer

首先,由于对象是指针,正如您从其他回复中了解到的,它的平台强制属性有助于区分真正的指针和有效的指针!和整数值。看看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的虚拟方法表的签名,并在给定内存读取操作成功且签名检查通过后将任意指针标识为对象或子实例


nil/0:您需要对0指针值采取更为特殊的预防措施,因为它作为指针非常有意义,作为整数也很常见。

a可以同时保存整数类型和类实例。没有安全的方法可以说您的整数指向实例化的类。最简单的方法是不要这样做,因为这很愚蠢。不要混合整数和对象,你就不会有这个问题。说真的,当你开始问这样的问题时,这是一个非常强烈的迹象,表明你做了一些完全错误的事情,摆脱这种情况的最好方法是停止做那些你做得非常错误以至于不得不问这个问题的事情。A可以包含整数类型和类实例。没有安全的方法可以说您的整数指向实例化的类。最简单的方法是不要这样做,因为这很愚蠢。不要混合整数和对象,你就不会有这个问题。说真的,当你开始问这样的问题时,这是一个非常强烈的迹象,表明你做了一些完全错误的事情,摆脱这种情况的最好方法是停止做你做得如此错误以至于不得不问这个问题的事情。而且,IIRC 32位窗口在地址空间顶部也有保留内存区域,这意味着可以识别哪些较小的负值。VMT参考+1-参见VMTSELFTR constantAlso,IIRC 32位窗口在地址空间顶部也有保留内存区域,也就是说可以识别哪些较小的负值。VMT参考值为+1-请参阅VMTSELFTR常量