堆利用

這裏給哪些初學者學堆的一些簡單的講解,

什麼是堆?
在程序運行過程中,堆可以提供動態分配的內存,允許程序申請大小未知的內存。堆其實就是程序虛擬地址空間的一塊連續的線性區域,它由低地址向高地址方向增長。我們一般稱管理堆的那部分程序爲堆管理器。
堆管理器處於用戶程序與內核中間,主要做以下工作
響應用戶的申請內存請求,向操作系統申請內存,然後將其返回給用戶程序。同時,爲了保持內存管理的高效性,內核一般都會預先分配很大的一塊連續的內存,然後讓堆管理器通過某種算法管理這塊內存。只有當出現了堆空間不足的情況,堆管理器纔會再次與操作系統進行交互。
管理用戶所釋放的內存。一般來說,用戶釋放的內存並不是直接返還給操作系統的,而是由堆管理器進行管理。這些釋放的內存可以來響應用戶新申請的內存的請求。
Linux 中早期的堆分配與回收由 Doug Lea 實現,但它在並行處理多個線程時,會共享進程的堆內存空間。因此,爲了安全性,一個線程使用堆時,會進行加鎖。然而,與此同時,加鎖會導致其它線程無法使用堆,降低了內存分配和回收的高效性。同時,如果在多線程使用時,沒能正確控制,也可能引起內存分配和回收的正確性。Wolfram Gloger 在 Doug Lea 的基礎上進行改進使其可以支持多線程,這個堆分配器就是 ptmalloc 。在 glibc-2.3.x. 之後,glibc 中集成了ptmalloc2。
目前 Linux 標準發行版中使用的堆分配器是 glibc 中的堆分配器:ptmalloc2。ptmalloc2 主要是通過 malloc/free 函數來分配和釋放內存塊。
需要注意的是,在內存分配與使用的過程中,Linux有這樣的一個基本內存管理思想,只有當真正訪問一個地址的時候,系統纔會建立虛擬頁面與物理頁面的映射關係。 所以雖然操作系統已經給程序分配了很大的一塊內存,但是這塊內存其實只是虛擬內存。只有當用戶使用到相應的內存時,系統纔會真正分配物理頁面給用戶使用。
x64位
在這裏插入圖片描述堆是從低地址向高地址
kernel space是內核空間
堆是增刪查改
在這裏插入圖片描述malloc的介紹
**/
malloc (size_t n)
返回一個指針,指向新分配的至少n個字節的塊,或null
如果沒有可用的空間。此外,在失敗時,errno是
在ANSI C系統上設置ENOMEM。
如果n爲零,malloc返回一個最小大小的塊。(最低
大小在大多數32位系統上是16字節,在64位系統上是24或32字節
系統)。在大多數系統中,size_t是無符號類型,所以調用
用否定的論點會被解釋爲要求大量的錢
空間,這往往會失敗。n的最大支持值
系統之間是不同的,但在所有情況下都小於t
**/
上面可以看出:
malloc函數返回對應大小字節的內存塊的指針,此外,該函數還可以對一些異常情況進行的處理,
當n=0時,返回當前的系統允許的堆的最小內存塊,
當n爲負數時,由於在大多數系統上,size_t是無符號數,這裏的程序就會申請很大的內存空間,但這系統是報錯的,因爲系統沒有那麼內存可以分配。

chunk是什麼呢
是堆的最小操作單元,不可分割單元,是最基礎,
chunk就是一個結構體
在這裏插入圖片描述prev_size和size是chunk頭(top chunk)
上面的prev_size = 8byte
size代表當前chunk的大小,包括chunk頭
在這裏插入圖片描述size of previous對應是上面chunk的prev_size
在這裏插入圖片描述在這裏是二進制代表標誌位
malloc是堆的分配作用
而free是堆的回收作用
在這裏插入圖片描述瞭解一個對齊,是一個地址對齊
size_t = 8字節,

接下來編譯:
寫好的代碼,用subl可以查看源碼,
在這裏插入圖片描述在malloc,在堆申請0x10空間
在這裏插入圖片描述接下來就用gdb調試

b malloc
r
heap
vmmap查看內存權限

在這裏插入圖片描述會報錯,在malloc沒有分配空間
在這裏插入圖片描述如果繼續c的話,會下在下一個斷點,第一的malloc已經分配了
這個我下去heap,這個會出錯,就改了一下源碼,在前面加了,sleep(0.1),
這就需要重新編譯一下:

gcc 文件的.c -o 文件名()
接下去就要斷在sleep上面,b sleep
c繼續運行
heap

在這裏插入圖片描述c繼續運行後heap下,用heap查看,可以看出,堆沒有被初始化

就可以看到prev_size=0x0
size=0x21是申請的空間
真正的size=chunk頭+申請的大小=0x21

在這裏插入圖片描述size是top chunk地址
在這裏插入圖片描述分析chunk x/4gx 地址 /////查看內存信息
在這裏插入圖片描述
真正的size = chunk+申請大小 ///上面的哪個0x21
這裏chunk是0x10 ,malloc是0x10,
0x1是fasbin的inyou位置於1(也就是下面圖的p)
標誌位p是用二進制表示,
當爲1是chunk使用中
當爲0時chunk沒有使用中在這裏插入圖片描述在這裏插入圖片描述chunk格式
在這裏插入圖片描述fd和bk是在chunk被使用
在這裏插入圖片描述fd和bk是鏈表,(指向的是前一個鏈表和後一個指針)
ps:fasbin是單鏈,smalloc是雙鏈,
fd指向下一個空閒的chunk
bk指向上一個空閒的chunk
單雙鏈表的最小操作單元是節點(note)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章