簡體   English   中英

delete[] 如何“知道”操作數數組的大小?

[英]How does delete[] "know" the size of the operand array?

Foo* set = new Foo[100];
// ...
delete [] set;

您沒有將數組的邊界傳遞給delete[] 但是這些信息存儲在哪里呢? 是否標准化?

當您在堆上分配內存時,您的分配器將跟蹤您分配了多少內存。 這通常存儲在您分配的內存之前的“頭”段中。 這樣,當需要釋放內存時,解除分配器確切地知道要釋放多少內存。

編譯器的一種方法是分配更多的內存並在頭元素中存儲元素計數。

示例如何完成:

這里

int* i = new int[4];

編譯器將分配sizeof(int)*5字節。

int *temp = malloc(sizeof(int)*5)

將在第一個sizeof(int)字節中存儲“4”

*temp = 4;

並設置i

i = temp + 1;

所以i將指向一個包含 4 個元素的數組,而不是 5 個。

並刪除

delete[] i;

將按以下方式處理:

int *temp = i - 1;
int numbers_of_element = *temp; // = 4
... call destructor for numbers_of_element elements
... that are stored in temp + 1, temp + 2, ... temp + 4 if needed
free (temp)

信息不規范。 但是,在我處理過的平台中,此信息存儲在第一個元素之前的內存中。 因此,理論上您可以訪問它並檢查它,但它不值得。

這也是為什么當您使用 new [] 分配內存時必須使用 delete [],因為 delete 的數組版本知道(以及在哪里)它需要尋找釋放適當數量的內存 - 並調用適當數量的析構函數為對象。

它在 C++ 標准中定義為特定於編譯器。 這意味着編譯器魔法。 它可以打破至少一個主要平台上的非平凡對齊限制。

您可以通過意識到delete[]只為new[]返回的指針定義,這可能與operator new[]返回的指針不同,來考慮可能的實現。 在野外的一個實現是將數組計數存儲在operator new[]返回的第一個 int 中,並讓new[]返回一個指針偏移量。 (這就是為什么非平凡的對齊會破壞new[] 。)

請記住operator new[]/operator delete[] != new[]/delete[]

另外,這與 C 如何知道malloc分配的malloc大小是正交的。

基本上它在內存中排列為:

[信息][你要求的記憶...]

其中 info 是編譯器用來存儲分配的內存量的結構,什么不是。

不過,這取決於實現。

這不是規范中的內容——它依賴於實現。

因為要“刪除”的數組應該是使用一次“new”運算符創建的。 'new' 操作應該將該信息放在堆上。 否則,new 的其他用途如何知道堆在哪里結束?

它不是標准化的。 在 Microsoft 的運行時中,new 運算符使用 malloc(),而 delete 運算符使用 free()。 因此,在這種情況下,您的問題相當於以下內容: free() 如何知道塊的大小?

幕后有一些簿記工作,即在 C 運行時。

這是一個比您最初想象的更有趣的問題。 這個回復是關於一種可能的實現。

首先,雖然在某種程度上您的系統必須知道如何“釋放”內存塊,但底層的 malloc/free(通常調用 new/delete/new[]/delete[])並不總是准確地記住多少內存您要求,它可以四舍五入(例如,一旦超過 4K,它通常會四舍五入到下一個 4K 大小的塊)。

因此,即使可以獲取內存塊的大小,也不能告訴我們 new[]ed 內存中有多少個值,因為它可以更小。 因此,我們必須存儲一個額外的整數,告訴我們有多少個值。

除了,如果正在構造的類型沒有析構函數,則 delete[] 除了釋放內存塊之外不需要做任何事情,因此不需要存儲任何東西!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM