簡體   English   中英

C++ 刪除一個指針(空閑內存)

[英]C++ delete a pointer (free memory)

考慮以下代碼:

int a = 10;
int * b = &a;
int * c = b;
delete b; // equivalent to delete c;

我對最后一行的理解是否正確, delete bdelete c是等效的,並且兩者都將釋放保存a的內存空間,因此a不再可訪問?

你的程序的行為是undefined 只能在使用new分配的內存指針上使用delete 如果你寫過

int* b = new int;
*b = 10;
int* c = b;

然后你可以或者delete b; delete c; 釋放你的記憶。 不要嘗試在delete調用之后取消引用bc ,這樣做的行為也是undefined

如果bc指向相同的內存,則刪除它們中的任何一個都會釋放內存,因此假設是正確的。 a不可訪問是不是在這種情況下,正確的,雖然你不指向動態分配的內存,你只能叫delete / delete[]對與創建一些new / new[] 嘗試delete / delete[]一個沒有用new / new[]分配的指針是未定義的行為,通常會以段錯誤結束。

令人困惑的部分是您問題的答案

我在最后一行中的理解是否正確,刪除 b 和刪除 c 是等效的”

是的,它們是等效的,並且這里的其他地方都提到了 UB。

你永遠不應該對在堆棧上分配的變量使用 delete,delete 是 new 的對應物。 因此,當不使用 new/alloc 時,不需要刪除/釋放,一旦超出代碼的“范圍”(在這種情況下是程序本身),所有內存都被認為是可用的。

這個特定的答案使用堆的特定實現來詳細說明在您提出的情況下會發生什么; 然而這很重要,因為其他版本仍然會有類似的問題接近我提供的論點。

答案是“不”,這是因為其他人所說的。 但是,我會更准確一些,因為我認為你實際上並不知道堆棧和堆是什么,所以我會花時間來解釋你。

現在首先,關於堆的細節,我所說的一切都是“謊言”。 沒有人具體知道您的編譯器實現堆的功能。 所以,我只能給我一堆的理解來代替。

新建和刪除實際上是兩個函數(如果你已經聽說過運算符重載,你會理解我的意思)接受指針並修改內存中的數據結構,稱為堆。 它是C / C ++程序內存中的四個主要數據結構之一(堆,堆棧,文本和靜態空間)。

堆本質上是一個鏈表,但不是在每個節點中存儲數據,而是將數據填入它們之間。 如果您不熟悉鏈接列表,那么在此上下文中,它是一個位於原始內存中的雙組件“數組”。 第二個組件是存儲在它前面的塊的長度。 第一個組件是它之前的塊的長度。 以這種方式很容易找到一個塊,因為它只是向下移動列表搜索塊。 通常(因為程序甚至不夠復雜到需要在單個塊內分配2 ^ 31個字節),最左邊的位用作表示塊是否空閑的真/假值。 因此,free和new只是列表上的操作而且free只需將指針向上移動一個來查看節點並進行適當的更改。 我不會詳細介紹,因為那些熟悉雙重鏈表的人應該理解這些操作,如果你不理解,那我就沒有必要教你一些你將在更深層次的深度學習的東西。

請記住:您的實現因編譯器而異。 這只是一個例子。

另一方面,堆棧是局部變量所在的位置。 它實際上是一個龐大的數組陣列。 數組的中間保存程序執行后應返回的代碼中的地址,然后參數位於一側,而局部變量位於另一側。 局部變量沒有明確的組織意識。 有些編譯器可能會檢測到一個值在另一個值之前停止使用並且只是共享內存位置(除非你真正偷看內存或掃描堆棧,否則你永遠不會注意到)。

如你所見,這兩者根本沒有意義。 在索引堆棧的指針上自由調用意味着您嘗試在堆棧上執行列表操作。 將發生以下兩件事之一:

  1. 您的實現檢測到內存甚至不在堆中,並且出現錯誤消息(非法參數異常)。

  2. 實現是“啞”,實際上嘗試執行列表操作。 這意味着內存中變量之前的值將被更改,並且可能會更改其他值以嘗試將兩個空閑塊“合並”為一個更大的塊。

簡單地說:不要那樣做。 你可能會在程序中破壞某些東西。 如果你搞砸了回程線怎么辦? 接下來你知道,你有一個無限的函數調用循環......你沒有寫過循環。 非常非常糟糕。

而且當然:

你對堆的確切實現會有很大的不同,不像堆棧不會發生太大變化。

例如,雖然我從未真正看到過這種結構的原始內存的代碼或圖表,但我聽說有堆空間的模型圍繞着兩個單獨的列表來保存釋放的塊和分配的塊。 這不會影響這個問題,因為仍有某種形式的內部簿記處理分配。

暫無
暫無

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

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