我希望在以下函数中获得任何“记录”类型的大小。但似乎它不起作用:
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指向的类型大小的内存块。怎么能达到这个尺寸?
答案 0 :(得分:7)
New
知道要分配多少内存的原因是New
是编译器魔法。它是一种内置的语言,所以当编译器看到你调用它时,它会将它重写为如下所示:
// New(foo);
foo := System._New(SizeOf(foo^), TypeInfo(TypeOf(foo^)));
TypeOf
这是一个用于说明目的的Delphi函数。编译器知道foo
的声明类型,因为它知道所有变量声明的位置。您可以在 System.pas 中查看_New
的实现。对Dispose
进行了类似的重写,因此它知道在释放内存之前要做什么样的终结。
变量和声明的概念是编译时概念。在运行时,它们不复存在。在运行时,指针只是一个地址。它指向的类型是在编译时确定的。类型决定了某些东西的大小。
如果你需要编写一个接受指向不同大小的多个东西的指针的函数,那么你只需要提供第二个参数来描述第一个指向的内容。
在这里查看另一个问题,“How to know what type is a var。”提问者想知道如何仅根据地址确定有关变量的更多信息。
答案 1 :(得分:3)
你无法使用Pointer类型的变量找到数据结构的大小,因为编译器不能,猜测并检查它,因为指针可以指向你能想到的任何数据类型。您可以阅读一些信息here。
答案 2 :(得分:2)
没有安全的方法来确定指针所指向的记录的大小。但是,如果您分配了指针指向的内存,则可以询问该内存块的大小。但话说回来,因为你分配了那个块,你应该已经知道了那个块的大小! Delphi内存管理器跟踪分配的每个内存块。使用来自内存管理器的信息,如果指针指向内存块的开头,则可以找到此信息。但是,如果你分配了一大块内存,在其中加载了一些数据,并且你的指针指向了这个块中的一些数据,那么这种方法将非常不可靠。
此外,如果您在记录中使用引用的类型(动态数组,字符串,类等),它返回的大小仍将无法使用,因为您获得了引用的大小(4个字节)而不是大小引用的数据。
NEW()命令只使用传递给它的数据类型的类型信息来获取它的大小。要知道它是如何做到这一点,你可以检查Delphi源代码。打开\ source \ Win32 \ rtl \ sys \ System.pas并搜索“_New”。 (使用下面的下划线。使用此源代码可能有助于您了解Delphi如何处理内存分配,尽管源代码可能非常复杂。
答案 3 :(得分:0)
Delphi有一个内置的内存管理器。我相信 new 可以访问堆对象并使用 HeapSize()(或类似的例程)来获取块的大小,对于某些指针。