2009-06-09 71 views
1

我想在下面的函數中獲取任何「記錄」類型的大小。但是看來它不工作:是否可以獲取指針在Delphi 7中指向的類型的大小?

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指向的類型的大小。它如何獲得大小?

回答

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」。提問者想知道如何確定更多關於變量的信息,只給出它的地址。

+0

@Rob,感謝您的詳細信息,我相信這是編譯器的魔力。我認爲這也解釋了爲什麼沒有「新」程序。 – trudger 2009-06-09 15:39:46

0

Delphi有一個內置的內存管理器。我相信新的可以訪問堆對象,並使用HeapSize()(或類似的例程)來獲取某個指針塊的大小。

+0

內存管理器是可替換的,但是這個能力是定義的一部分。像ansistrings和動態數組等關鍵功能將不會沒有它的工作。 – 2009-06-12 20:53:45

3

由於指針可以指向任何可以想到的數據類型,因此編譯器無法進行猜測並檢查它,所以無法使用指針類型的變量找到數據結構的大小。你可以閱讀一些信息here

2

沒有安全的方法來確定指針指向的記錄的大小。但是,如果您分配了指針指向的內存,則可以詢問該內存塊的大小。但是,再次,因爲您已經分配了該塊,您應該已經知道該塊的大小! Delphi內存管理器記錄分配的每塊內存。有了內存管理器的信息,如果指針指向內存塊的開始,就可以找到這些信息。但是,如果你分配了一大塊內存,在其中加載了一些數據,而你的指針指向了這個塊內的一些數據,這種方法將是相當不可靠的。另外,如果您在記錄中使用引用類型(動態數組,字符串,類等),則它返回的大小將仍然不可用,因爲您獲取引用的大小(4個字節)而不是大小的參考數據。

NEW()命令只是使用傳遞給它的數據類型的類型信息來獲取它的大小。要知道它是如何做到這一點,你可以檢查Delphi的源代碼。打開\ source \ Win32 \ rtl \ sys \ System.pas並搜索「_New」。 (隨着它前面的下劃線。使用這個源代碼可以幫助你瞭解德爾福如何處理內存分配,雖然源代碼可真複雜。

相關問題