記憶體中堆的基本概念

2021-10-09 11:41:37 字數 1564 閱讀 2262

c語言堆是由malloc(),calloc(),realloc()等函式動態獲取記憶體的一種機制。使用完成後,由程式設計師呼叫free()等函式進行釋放。使用時,需要包含stdlib.h標頭檔案。

c++預言的堆管理則是使用new操作符向堆管理器申請動態記憶體分配,使用delete操作符將使用完畢記憶體的釋放給堆管理器。

要動態管理一片記憶體,且需要動態分配釋放,這樣乙個需求。很顯然c語言需要將動態記憶體區抽象描述起來並實現動態管理。事實上,c語言中堆管理器其本質是利用資料結構將堆區抽象描述,所需要描述的方面:

再利用相應演算法對於這類資料結構物件進行動態管理而實現的堆管理器。

經常看到各種演算法書很多只講演算法原理,而不講應用例項,往往體會不深。私以為可以做些改善。學而不能致用,何必費力去學。所以不是晦澀難懂的演算法無用,而是沒有去真正結合應用。可以再進一步想,如果演算法沒有應用場景,也一定會在技術發展的歷程中逐漸被世人遺忘。所以建議學習閱讀演算法書籍時,找些例項來看看,一定會加深對演算法的理解領悟。這是比較重要的題外話,送給大家以共勉。

所以從本質上講,堆管理器就是資料結構+演算法實現的動態記憶體管理器,管理記憶體的動態分配以及釋放。

c程式語言對記憶體管理方式有靜態,自動或動態三種方式。靜態記憶體分配的變數通常與程式的可執行**一起分配在主儲存器中,並在程式的整個生命週期內有效。自動分配記憶體的變數在棧上分配,並隨著函式的呼叫和返回而申請或釋放。對於靜態分配記憶體和自動分配記憶體的生命週期,分配的大小必須是編譯時常量(可變長度自動陣列[5]除外)。如果所需的記憶體大小直到執行時才知道(例如,如果要從使用者或磁碟檔案中讀取任意大小的資料),則使用固定大小的資料物件則滿足不了要求了。試想,即便假定都知道要多大記憶體,如在windows/linux下有那麼多應用程式,每個應用程式載入時都將執行中所需的記憶體取樣靜態分配策略,則如多個程式執行記憶體將很快耗盡。

分配的記憶體的生命週期也可能引起關注。靜態或自動分配都不能滿足所有情況。自動分配記憶體不能在多個函式呼叫之間保留,而靜態資料在程式的整個生命週期中必然保留,無論是否真正需要(所以都採用這樣的策略必然造成浪費)。在許多情況下,程式設計師在管理分配的記憶體的生命週期具有更多的靈活性。

通過使用動態記憶體分配則避免了這些限制/缺點,在動態記憶體分配中,更明確(但更靈活)地管理記憶體,通常是通過從免費儲存區(非正式地稱為「堆」)中分配記憶體(為此目的而構造的記憶體區域)進行分配的。在c語言中,庫函式malloc用於在堆上分配乙個記憶體塊。程式通過malloc返回的指標訪問該記憶體塊。當不再需要記憶體時,會將指標傳遞給free,從而釋放記憶體,以便可以將其用於其他目的。

堆可實現動態記憶體管理的多樣性,在犧牲一定開銷情況下(申請/釋放開銷,以及記憶體開銷),可以提供記憶體的利用率,在一定程度上解決記憶體不足的需求。

如果一問到這個問題,馬上會說c編譯器。不錯c編譯器實現了堆管理器,而事實上並非編譯器在編譯的過程中實現動態記憶體管理器,而是c編譯器所實現的c庫實現了堆管理器,比如ansi c,vc, iar c編譯器,gnu c等其實都需要一些c庫的支援,那麼這些庫的內部就隱藏了這麼乙個堆管理器。作業系統核心也可能實現堆管理器。

堆和棧的基本概念

堆 heap 和棧 stack 是c c 程式設計不可避免會碰到的兩個基本概念。首先,這兩個概念都可以在講資料結構的書中找到,他們都是基本的資料結構,雖然棧更為簡單一些。在具體的c c 程式設計框架中,這兩個概念並不是並行的。對底層機器 的研究可以揭示,棧是機器系統提供的資料結構,而堆則是c c 函...

虛擬記憶體基本概念

傳統儲存管理分為連續分配與非連續分配。連續分配分為單一連續分配 固定分割槽分配 動態分割槽分配 非連續分配包括基本分頁儲存管理 基本分段儲存管理 基本段頁式儲存管理。傳統儲存管理由於暫時用不到的資料也長期占用記憶體所以導致記憶體利用率不高。傳統儲存管理的特點就是一次性與駐留性。時間區域性性 如果執行...

堆的基本概念及常用操作

二叉堆滿足二個特性 1 父結點的鍵值總是大於或等於 小於或等於 任何乙個子節點的鍵值 2 每個結點的左子樹和右子樹都是乙個二叉堆 都是最大堆或最小堆 當父結點的鍵值總是大於或等於任何乙個子節點的鍵值時為最大堆。當父結點的鍵值總是小於或等於任何乙個子節點的鍵值時為最小堆 堆的主要操作是插入和刪除最小 ...