malloc申請堆記憶體

2021-10-10 09:07:34 字數 4584 閱讀 1694

malloc申請空間時,記錄其空間大小(其空間上方,有乙個資料頭,頭部資訊就記錄了申請空間的大小),當呼叫free函式時,即需要讀取頭部資訊得到需要釋放的位元組數

malloc申請的空間,一 申請的記憶體 小的靠近資料區 ,大的靠近棧區,而中間的是「無人區」」

malloc工作在user space(使用者態),是以什麼樣的資料結構組織從核心中申請分配一大塊記憶體?

核心態(資源都是由os管理的)和使用者態互動(呼叫系統api open、close、read、write )

malloc第一次向核心申請(申請堆記憶體的系統api)brk()(增加或減小brk指標相當於申請和回退申請的記憶體)和mmap()(將磁碟上的頁面載入到虛擬位址空間上) 申請的單位是頁面,申請後返回申請整個記憶體的起始位址,然後將使用者申請的多少位元組返回給使用者,其他空間由malloc函式庫(使用者態)來管理,此後使用者申請的小記憶體不需要要向os申請。

malloc(0)也會申請記憶體資源

malloc(-10) 拒接不做任何處理

int

*p =

(int*)

malloc

(sizeof

(int)*

10);if(null

==p)exit(1

);//malloc申請之後,一定要記得檢測其是否申請成功(為了多執行緒安全)!

申請空間時,為其分配了40個位元組的空間作為資料空間(即使用者需要的),還分配了8個位元組的越界標記,這個應該和棧的carray技術一樣,檢查越界的,所以發生越界錯誤時,是在free時才會檢測出來錯誤,free也只是在呼叫free時才發現才去即時制止。同時還會分配頭部空間的位元組,來記錄malloc分配的空間大小20位元組 40+8+20=40+28,即系統還會多提供32位元組的記憶體(頭部空間大小不,一般int 20 char 24)

free的越界標記是針對於malloc函式庫的,標記位是面向系統的。

同時free其實進行了堆空閒塊的合併

在這種情況中**,乙個塊是由乙個字的頭部、有效載荷,以及可能的一些額外的填充組成的。頭部編碼了這個塊的大小(包括頭部和所有的填充),以及這個塊是已分配的還是空閒的。如果我們強加乙個雙字的對齊約束條件**,那麼塊大小就總是8的倍數,且塊大小的最低3位總是零。因此,我們只需要記憶體大小的29個高位,釋放剩餘的3位來編碼其他資訊。在這種情況中,我們用其中的最低位(已分配位)來指明這個塊是已分配的還是空閒的。例如,假設我們有乙個已分配的塊,大小24(0x18)位元組。那麼它的頭部將是

0x00000018 l 0x1 = 0x00000019

類似地,乙個塊大小為40(ox28)位元組的空閒塊有如下的頭部:

0x00000028 i 0x0 = 0x00000028

頭部後面就是應用呼叫malloc時請求的有效載荷。有效載荷後面是一片不使用的填充塊,其大小可以是任意的。需要填充有很多原因。比如,填充可能是分配器策略的一部分,用來對付外部碎片。或者也需要用它來滿足對齊要求。

隱式空閒鍊錶

我們稱這種結構為隱式空閒鍊錶,是因為空閒塊是通過頭部中的大小字段隱含地連線著的。分配器可以通過遍歷堆中所有的塊,從而間接地遍歷整個空閒塊的集合。注意,我們需要某種特殊標記的結束塊,在這個示例中,就是乙個設定了已分配位而大小為零的終止頭部(ter-minating header)。

隱式空閒鍊錶的優點是簡單。顯著的缺點是任何操作的開銷,例如放置分配的塊,要求對空閒鍊錶進行搜尋,該搜尋所需時間與堆中已分配塊和空閒塊的總數呈線性關係。

很重要的一點就是意識到系統對齊要求和分配器對塊格式的選擇會對分配器上的最小塊大小有強制的要求。沒有已分配塊或者空閒塊可以比這個最小值還小。例如,如果我們假設乙個雙字的對齊要求,那麼每個塊的大小都必須是雙字(8位元組)的倍數。因此,圖9-35中的塊格式就導致最小的塊大小為兩個字:乙個字作頭,另乙個字維持對齊要求。即使應用只請求一位元組,分配器也仍然需要建立乙個兩字的塊。

#include

#include

struct foo

;struct foo *

foo_alloc

(void

)/* allocate the object */

/* continue initialization */

}return

(fp);}

void

foo_hold

(struct foo *fp)

/* add a reference to the object */

void

foo_rele

(struct foo *fp)

/* release a reference to the object */

else

}

對於多個物件利用堆區時。

在使用該物件前,執行緒需要對這個物件的引用計數加1,當物件使用完畢時,需要對引用計數減1。當最後乙個引用被釋放時,物件所佔的記憶體空間就被釋放。在對引用計數加1、減1以及檢查引用計數是否為0這些操作之前需要鎖住互斥量。

當堆記憶體滿時,可以利用虛擬記憶體來進行。

虛擬記憶體(計算機系統記憶體管理)(cache和主存構成了系統的記憶體,而主存和輔存依靠輔助軟硬體的支援構成了虛擬儲存器。 )

虛擬記憶體是計算機系統記憶體管理的一種技術。它使得應用程式認為它擁有連續的可用的記憶體(乙個連續完整的位址空間),而實際上,它通常是被分隔成多個物理記憶體碎片,還有部分暫時儲存在外部磁碟儲存器上,在需要時進行資料交換。目前,大多數作業系統都使用了虛擬記憶體,如windows家族的「虛擬記憶體」;linux的「交換空間」等。

虛擬記憶體別稱虛擬儲存器(virtual memory)。電腦中所執行的

程式均需經由記憶體執行,若執行的程式占用記憶體很大或很多,則會導致記憶體消耗殆盡。為解決該問題,windows中運用了虛擬記憶體技術,即勻出一部分硬碟空間來充當記憶體使用。當記憶體耗盡時,電腦就會自動呼叫硬碟來充當記憶體,以緩解記憶體的緊張。若計算機執行程式或操作所需的隨機儲存器(ram)不足時,則 windows 會用虛擬儲存器進行補償。它將計算機的ram和硬碟上的臨時空間組合。當ram執行速率緩慢時,它便將資料從ram移動到稱為「分頁檔案」的空間中。將資料移入分頁檔案可釋放ram,以便完成工作。 一般而言,計算機的ram容量越大,程式執行得越快。若計算機的速率由於ram可用空間匱乏而減緩,則可嘗試通過增加虛擬記憶體來進行補償。但是,計算機從ram讀取資料的速率要比從硬碟讀取資料的速率快,因而擴增ram容量(可加記憶體條)是最佳選擇。

工作原理

虛擬儲存器是由硬體和作業系統自動實現儲存資訊排程和管理的。它的工作過程包括6個步驟:

①**處理器訪問主存的邏輯位址分解成組號a和組內位址b,並對組號a進行位址變換,即將邏輯組號a作為索引,查位址變換表,以確定該組資訊是否存放在主存內。

②如該組號已在主存內,則轉而執行④;如果該組號不在主存內,則檢查主存中是否有空閒區,如果沒有,便將某個暫時不用的組調出送往輔存,以便將這組資訊調入主存。

③從輔存讀出所要的組,並送到主存空閒區,然後將那個空閒的物理組號a和邏輯組號a登入在位址變換表中。

④從位址變換表讀出與邏輯組號a對應的物理組號a。 [

⑤從物理組號a和組內位元組位址b得到實體地址。

⑥根據實體地址從主存中訪問必要的資訊。

記憶體洩漏(memory leak)是指程式中已動態分配的堆記憶體由於某種原因程式未釋放或無法釋放,造成系統記憶體的浪費,導致程式執行速度減慢甚至系統崩潰等嚴重後果。(程式還在執行,沒有退出。)

記憶體洩漏缺陷具有隱蔽性、積累性的特徵,比其他記憶體非法訪問錯誤更難檢測。因為記憶體洩漏的產生原因是記憶體塊未被釋放,屬於遺漏型缺陷而不是過錯型缺陷。此外,記憶體洩漏通常不會直接產生可觀察的錯誤症狀,而是逐漸積累,降低系統整體效能,極端的情況下可能使系統崩潰。

記憶體洩露不是簡單的沒有進行delete和free

1.丟失位址

2.執行的堆空間滿了,就將所有的記憶體空間都申請完了,無法執行了,系統甚至崩潰(系統無法回寫資料),且此時記憶體空間無法釋放?

3.物件沒有析構,直接呼叫free進行釋放?是因為標記位沒有處理嗎? 沒有虛函式時可以偷懶直接進行空間對物件的賦值嗎?

作業系統**資源是指,當程式(程序)結束後,程式所使用的資源都會被作業系統**。但是如果程式一直在執行的話, 如果你不主動釋放空間的話,用new申請的空間是不會被**的。此時將標記位改變。

1.堆記憶體申請釋放,利用執行緒,乙個執行緒來統計其空間被多少執行緒使用,另乙個執行緒判斷其空間沒人使用則釋放,需要讀寫鎖。

2.堆記憶體申請釋放,利用繼承機制,父類來申請空間,子類使用空間,子類析構,父類釋放空間(利用棧機制,但一般理解子類物件為構造時,先對父類構造,再對子類構造,析構時,先對子類析構,再對父類釋放) 即父類和子類的責任分離,乙個負責申請釋放,乙個負責使用析構。

malloc動態申請記憶體

1 malloc概述 malloc num 動態申請num位元組的記憶體空間,函式申請成功返回記憶體的起始位址 void型 申請不成功返回null指標,malloc不初始化記憶體空間 calloc type,num 函式會初始化申請的記憶體空間為0 使用完申請的記憶體後需要用free p 釋放記憶體...

new 與malloc申請記憶體區別

首先我們需要了解堆與棧的概念。區分堆記憶體與棧記憶體的區別。以及堆與棧訪問速度的差異的原因。1.屬性 new delete是c 關鍵字,需要編譯器支援。malloc free是庫函式,需要標頭檔案支援。2.引數 使用new 操作副申請記憶體分配時無須制定記憶體塊的大小,編譯器會根據型別資訊自行計算。...

關於動態申請記憶體malloc的知識

關於malloc申請記憶體的函式 一 定義 malloc函式是一種分配長度為num bytes位元組的記憶體塊的函式,可以向系統申請分配指定size個位元組的記憶體空間。malloc的全稱是memory allocation,中文叫動態記憶體分配,函式返回的型別是void 型別。void 表示未確定...