1

我想在以下函数中获取任何“记录”类型的大小。但似乎它不起作用:

function GetDataSize(P : Pointer) : Integer;
begin
  Result := SizeOf(P^); // **How to write the code?**
end;

例如,以下记录的大小为 8 个字节

SampleRecord = record
 Age1 : Integer;
 Age2 : Integer;
end;

GetDataSize(@a)总是返回 1(a 当然是 SampleRecord 类型的变量)。我该怎么办?

我注意到 Delphi 有一个过程过程 New(var P: Pointer)可以分配内存块对应于 P 指向的类型的大小。它如何获得大小?

4

4 回答 4

7

New知道要分配多少内存的原因New编译器的魔力。它是一种内置语言,所以当编译器看到你调用它时,它会将其重写为如下内容:

// New(foo);
foo := System._New(SizeOf(foo^), TypeInfo(TypeOf(foo^)));

TypeOf这是一个用于说明目的的虚构 Delphi 函数。编译器知道声明的类型,foo因为它知道所有变量声明的位置。您可以查看System.pas_New中的实现。发生类似的重写,因此它知道在释放内存之前要执行哪种终结。Dispose

变量声明的概念是编译时概念。在运行时,它们不复存在。在运行时,指针只是一个地址。它指向的类型是在编译时确定的。类型决定了事物的大小。

如果您需要编写一个函数来接受指向不同大小的多个事物的指针,那么您只需要提供第二个参数来描述第一个指向的内容。

在这里查看另一个问题,“如何知道什么是 var 类型”。提问者想知道如何确定仅给定地址的变量的更多信息。

于 2009-06-09T14:20:02.657 回答
3

您无法使用指针类型的变量找到数据结构的大小,因为编译器无法猜测并检查它,因为指针可以指向您能想到的任何数据类型。你可以在这里阅读一些信息。

于 2009-06-09T10:09:23.350 回答
2

没有安全的方法来确定指针指向的记录的大小。但是,如果您分配了指针指向的内存,您可以询问该内存块的大小。但是话又说回来,既然你分配了那个块,你应该已经知道那个块的大小了!Delphi 内存管理器跟踪每个分配的内存块。如果您的指针指向内存块的开头,则可以使用来自内存管理器的信息找到此信息。但是,如果你分配了一大块内存,在其中加载了一些数据,并且你的指针指向了这个块内的一些数据,那么这种方法将非常不可靠。

此外,如果您在记录中使用引用类型(动态数组、字符串、类等),它返回的大小仍然不可用,因为您获得的是引用的大小(4 个字节)而不是数据的大小被引用。

NEW() 命令仅使用您传递给它的数据类型的类型信息来获取它的大小。要知道它是如何做到这一点的,您可以查看 Delphi 源代码。打开 \source\Win32\rtl\sys\System.pas 并搜索“_New”。(前面有下划线。使用此源代码可能会帮助您了解 Delphi 如何处理内存分配,尽管源代码可能非常复杂。

于 2009-06-09T11:53:43.483 回答
0

Delphi 有一个内置的内存管理器。我相信new可以访问堆对象并使用HeapSize()(或类似的例程)来获取块的大小,以获取某些指针。

于 2009-06-09T09:45:31.277 回答