成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

探秘glibc malloc:解鎖內存分配的黑匣子

開發 前端
當我們編寫 C 或 C++ 程序時,常常會遇到需要在運行時動態分配內存的情況。比如,你要創建一個動態數組來存儲用戶輸入的數據,由于用戶輸入的數據量是不確定的,靜態分配內存顯然無法滿足這種靈活性的需求,這時就輪到 glibc malloc 閃亮登場啦!

在程序的世界里,內存就像是一座大廈,而內存管理則是這座大廈的 “大管家”。它負責著內存的分配、釋放與管理,對于程序的穩定運行和性能表現起著至關重要的作用。而在眾多內存管理的 “工具” 中,glibc malloc 就像是一位默默奉獻卻神通廣大的幕后英雄,是我們深入理解內存管理繞不開的核心組件。

當我們編寫 C 或 C++ 程序時,常常會遇到需要在運行時動態分配內存的情況。比如,你要創建一個動態數組來存儲用戶輸入的數據,由于用戶輸入的數據量是不確定的,靜態分配內存顯然無法滿足這種靈活性的需求,這時就輪到 glibc malloc 閃亮登場啦!它能根據你的需求,在程序運行過程中靈活地為你分配內存空間,就像是一個貼心的 “內存快遞員”,及時把你需要的內存 “快遞” 到你的程序中。

一、glibc malloc概述

1.1什么是 glibc malloc

glibc malloc,簡單來說,它是 GNU C 庫(glibc)中用于動態內存分配的一個函數 。GNU C 庫可是 Linux 系統中 C 語言程序的基礎支持庫,提供了大量實用的函數,而 malloc 就是其中負責內存分配的關鍵角色。在 C 語言編程的世界里,它就如同建筑工人手中的 “萬能工具”,當你需要動態地創建和管理數據結構時,比如鏈表、樹、哈希表這些隨著程序運行而不斷變化的數據結構,glibc malloc 都能為它們分配所需的內存空間,確保程序能夠靈活地處理各種數據。

1.2工作機制初窺探

glibc malloc 的工作機制就像是一個精明的倉庫管理員在管理庫存。它通過維護一個空閑鏈表(Free List)來管理內存塊。這個空閑鏈表就像是倉庫里的 “空閑貨架”,上面存放著各種大小的空閑內存塊。當程序調用 malloc 函數申請內存時,它就會沿著這個空閑鏈表去尋找一個大到足以滿足用戶請求的內存塊。一旦找到合適的內存塊,它就會像切蛋糕一樣,將這個內存塊一分為二,一塊的大小與用戶請求的大小相等,另一塊則是剩下的字節。然后,它會將分配給用戶的那塊內存傳給用戶,就像是把切好的蛋糕遞給客人,而將剩下的那塊(如果有的話)重新放回空閑鏈表這個 “貨架” 上 。

當程序調用 free 函數釋放內存時,它又會將用戶釋放的內存塊連接到空閑鏈表上,就像是把歸還的物品重新放回貨架。不過,隨著不斷地分配和釋放內存,空閑鏈表會被切成很多小內存片段,就像一個完整的大蛋糕被切成了無數小塊。這時候,如果用戶申請一個大的內存片段,空閑鏈表上可能就沒有可以滿足要求的片段了。這可難不倒 glibc malloc,它會開啟 “整理模式”,在空閑鏈表上仔細檢查各內存片段,將相鄰的小空閑塊合并成較大的內存塊,以滿足大內存的分配需求。

二、深入剖析工作原理

2.1核心數據結構

⑴malloc_state

malloc_state 就像是內存分配的 “總指揮” 結構體,它在內存管理中扮演著極為關鍵的角色。在多線程環境下,內存分配就像是一場熱鬧的 “集市”,各個線程都可能來申請內存,這時候就需要一個協調者來維持秩序,malloc_state 中的互斥鎖(mutex)就承擔起了這個重要職責,它保證在同一時刻只有一個線程能夠訪問和修改內存分配相關的數據結構,避免了數據競爭和混亂,就像集市管理員維持秩序一樣 。

它還有一些標志位(flags),這些標志位就像是信號燈,用來記錄內存分配器的各種狀態信息,比如是否處于初始化階段,是否有內存碎片整理的需求等等,幫助 malloc 在不同情況下做出正確決策。各種鏈表指針也是 malloc_state 的重要成員,這些鏈表指針指向不同類型的內存塊鏈表,就像不同貨架的指引牌,讓 malloc 能快速定位和管理不同大小、不同狀態的內存塊,從而高效地進行內存分配和釋放操作 。

⑵malloc_chunk

malloc_chunk 則是內存分配的基本單位,是構成內存大廈的 “磚塊”。每個 malloc_chunk 都有一些成員,用來記錄內存塊的信息。它會記錄內存塊的大小,這就像給磚塊貼上了尺寸標簽,方便在分配和合并內存塊時快速了解其大小情況。它還有一些指針成員,用于實現鏈表操作,這些指針就像連接磚塊的 “膠水”,將各個內存塊連接成鏈表,使得內存分配器能夠方便地遍歷和管理這些內存塊,無論是在分配內存時從鏈表中查找合適的塊,還是在釋放內存時將塊重新插入鏈表,這些指針都發揮著不可或缺的作用 。

2.2內存分配流程

①小內存分配(fast bins 與 small bins)

當申請的內存小于 160 字節時,glibc malloc 會優先從 fast bins 中查找匹配的 chunk。fast bins 就像是一個小型的 “快速倉庫”,專門存放一些小的、最近剛剛釋放的內存塊,這些內存塊就像是放在倉庫門口的 “快捷物品”,可以快速地被分配出去。因為 fast bins 中的內存塊是按照大小分類存放的,所以 malloc 可以很快地找到合適大小的內存塊并分配給程序,就像在門口的貨架上快速找到所需物品一樣,大大提高了分配效率 。

對于 32 - 1008 字節的內存,small bins 就開始發揮作用了。small bins 也是一個鏈表結構,它存放著大小不同但相對較小的內存塊,每個 small bin 鏈表都存放著特定大小范圍的內存塊,就像一個個分類貨架。當有內存分配請求時,malloc 會依次遍歷這些 small bin 鏈表,尋找大小剛好等于請求大小的內存塊 。如果找到了,就直接將這個內存塊分配出去,這種精確匹配的方式保證了內存的高效利用,避免了大材小用造成的浪費。

②大內存分配(large bins 與 top chunk)

當申請的內存大于 1024 字節時,large bins 就上場了。large bins 存放的是較大的內存塊,這些內存塊就像是大型倉庫里的 “大件物品”。large bins 采用了一種特殊的分配策略,它會根據內存塊的大小范圍將其分組存放,這樣在查找時可以快速定位到合適的分組 。當有大內存分配請求時,malloc 會在 large bins 中查找大小大于或等于請求大小的最小內存塊,然后將其分配出去,就像在大型倉庫里找到剛好能裝下貨物的大箱子。

如果在 bins 中都沒有找到匹配的 chunk,這時候 top chunk 就派上用場了。top chunk 是位于堆頂的一塊特殊內存塊,就像是倉庫里的 “備用大倉庫”。當 bins 中沒有合適的內存塊時,malloc 會對 top chunk 進行裁剪,從 top chunk 中分割出一塊大小滿足請求的內存塊分配給程序 。如果 top chunk 的大小不夠,它還會嘗試向操作系統申請更多的內存來擴容,就像倉庫空間不夠時向周圍擴展空間一樣,以滿足程序對大內存的需求。

2.3內存釋放流程

當程序調用 free 函數釋放內存塊時,內存釋放流程就啟動了。free 函數會根據 chunk 的大小將其歸還到相應的鏈表中。如果是小內存塊,就會被歸還到 fast bins 或 small bins 中,就像把小物品放回對應的小貨架 。如果是大內存塊,就會被歸還到 large bins 中。在歸還過程中,如果發現相鄰的內存塊都是空閑的,就會觸發 chunk 合并操作。這就像在整理倉庫時,發現相鄰的空閑貨架可以合并成一個大貨架,就將它們合并起來,以減少內存碎片,提高內存利用率 。合并后的大內存塊會重新插入到合適的鏈表中,等待下一次的分配,從而實現了內存的循環利用,讓內存管理更加高效有序。

2.3實例解析

⑴代碼示例

#include <stdio.h>
#include <stdlib.h>

int main() {
    // 申請10個int類型大小的內存空間
    int* ptr = (int*)malloc(10 * sizeof(int)); 
    if (ptr == NULL) {
        printf("內存分配失敗\n");
        return 1;
    }

    // 使用分配的內存,這里簡單地對其進行賦值操作
    for (int i = 0; i < 10; i++) {
        ptr[i] = i; 
    }

    // 輸出內存中的值,以驗證內存使用情況
    for (int i = 0; i < 10; i++) {
        printf("%d ", ptr[i]); 
    }
    printf("\n");

    // 釋放已分配的內存
    free(ptr); 
    ptr = NULL; // 將指針置為NULL,避免野指針

    return 0;
}

在這段代碼中,malloc(10 * sizeof(int))這一步就像是向 glibc malloc 這個 “內存倉庫” 下了一個訂單,請求分配 10 個 int 類型大小的內存空間。glibc malloc 會根據我們之前介紹的原理,在它管理的內存空間中尋找合適的內存塊 。如果找到合適的內存塊,就會將其分配給程序,然后返回這塊內存的起始地址,我們把這個地址存儲在ptr指針中,就像是拿到了倉庫中對應內存塊的 “鑰匙”。

接下來的for (int i = 0; i < 10; i++) { ptr[i] = i; }這部分,是在使用分配到的內存,就像是往倉庫中對應內存塊里存放貨物。

最后,free(ptr)這一步是將使用完的內存歸還給 glibc malloc,就像是把倉庫中的貨物搬走后,把倉庫空間退還給倉庫管理員。ptr = NULL則是一個好習慣,它將指針置為 NULL,就像是把 “鑰匙” 扔掉,防止我們不小心再去使用已經歸還的內存空間,避免出現野指針問題 。

⑵運行分析

當程序運行到malloc函數時,glibc malloc 會先檢查空閑鏈表。如果請求的內存大小小于 160 字節,它會優先在 fast bins 中查找 。假設我們請求的 10 個 int 類型大小的內存(在常見的 32 位系統中,一個 int 通常占 4 字節,10 個 int 就是 40 字節,小于 160 字節),如果 fast bins 中有合適大小的空閑內存塊,它就會直接從 fast bins 中取出這塊內存塊分配給程序 。

如果 fast bins 中沒有合適的內存塊,它就會繼續在 small bins 中查找。當找到合適的內存塊后,glibc malloc 會將其從空閑鏈表中移除,然后返回給程序使用 。此時,這塊內存塊的狀態就從空閑變為已分配,就像是倉庫中的一塊空閑區域被租出去了。

在程序使用完內存,調用free函數時,這塊內存會被重新標記為空閑,并根據其大小被放回相應的鏈表中。如果它的大小在 fast bins 的管理范圍內,就會被放回 fast bins ;如果不在,就會被放回 unsorted bin,等待進一步的處理。在放回鏈表的過程中,如果發現相鄰的內存塊也是空閑的,就會觸發內存塊合并操作,就像把相鄰的空閑倉庫區域合并成一個更大的區域,以提高內存利用率 。這樣,這塊內存就又可以被其他程序請求使用了,實現了內存的循環利用。

三、優化技巧與注意事項

3.1優化技巧

在使用 glibc malloc 時,掌握一些優化技巧可以顯著提升程序的性能。比如采用批量內存分配的方式,當你需要分配多個小內存塊時,可以考慮一次性分配一個大的內存塊,然后在這個大內存塊中自行管理和劃分小內存區域 。這就好比你要開一家小超市,里面需要擺放各種商品貨架,與其每次需要一個貨架就去購買一個(頻繁小內存操作),不如一次性購買足夠多的貨架(批量內存分配),然后根據自己的需求在超市里自由擺放和調整,這樣可以大大減少內存分配的開銷,同時也能有效減少內存碎片的產生 。

避免頻繁的小內存操作也是一個重要的優化點。因為每次小內存分配和釋放都伴隨著一定的開銷,頻繁操作會導致程序性能下降 。就像你每次買一個小物品都要跑一趟超市,花費的時間和精力就會很多;但如果你把需要買的小物品列個清單,一次性去采購,就能節省很多時間和精力 。在代碼中,盡量合并小內存請求,將多個小內存分配合并成一個較大的內存分配,能有效提升程序運行效率。

3.2注意事項

在使用 glibc malloc 的過程中,需要特別注意一些常見問題,其中內存泄漏和懸空指針是最為突出的。內存泄漏就像是一個 “內存小偷”,當程序動態分配內存后,由于某種原因沒有釋放已分配的內存空間,這些內存就像被偷走了一樣,造成系統內存資源的浪費 。比如在 C 語言中,使用malloc分配了一塊內存空間,但在使用完后卻忘記調用free來釋放它,隨著程序的運行,泄漏的內存會越來越多,最終可能導致系統性能下降,甚至系統崩潰,就像一個倉庫里的貨物被不斷拿走卻不歸還,倉庫空間會越來越小,最終無法正常運轉 。

懸空指針則像是一個指向 “虛無” 的危險信號。當指針原來指向的內存已經被釋放,但指針本身沒有被置為NULL,仍然保存著之前內存的地址,再嘗試訪問這個指針所指向的已釋放內存,就會產生嚴重錯誤 。比如有兩個指針同時指向同一個動態分配的內存對象,然后其中一個指針通過free函數釋放了該內存,那么另一個指針就變成了懸空指針 。

這就像兩個人都拿著一把指向同一扇門的鑰匙,其中一個人把門鎖換了(釋放內存),但另一個人還拿著原來的鑰匙(指針),并試圖用它開門,這顯然是行不通的,還可能引發各種不可預測的問題,如程序崩潰、數據損壞等 。所以在編寫代碼時,一定要時刻警惕這些問題,養成良好的編程習慣,正確地分配和釋放內存,避免給程序埋下隱患 。

責任編輯:武曉燕 來源: 深度Linux
相關推薦

2023-11-27 14:48:34

人工智能深度學習大語言模型

2023-07-11 07:59:18

2022-03-25 13:56:37

黑匣子數據分析數據

2014-01-17 13:59:14

騰訊開放平臺

2022-04-12 14:13:01

云計算云存儲黑匣子

2013-03-27 10:40:29

2019-06-04 05:52:20

神經網絡可視化CNN)

2011-12-28 10:37:21

2021-09-16 09:09:03

“可解釋的”人工智能XAI人工智能

2023-09-20 11:42:44

人工智能AI

2025-06-18 02:00:00

人工智能AI大模型

2022-03-23 10:01:56

黑匣子云端

2015-10-12 15:13:45

銳捷網絡

2021-11-30 15:39:00

汽車智能技術

2022-03-23 19:05:25

黑匣子云端

2020-10-30 11:25:15

神經網絡人工智能黑匣子

2024-11-07 09:37:46

2024-08-12 10:52:00

AI模型

2022-01-07 17:31:48

阿里英偉達高通

2024-10-11 10:00:20

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产一级淫片a直接免费看 免费a网站 | 日韩在线视频播放 | 欧美日韩在线播放 | 可以免费看的毛片 | 免费黄色日本 | 欧美黄色一级毛片 | 久久精品国产亚洲一区二区三区 | 亚洲精色| 国产精品久久久久久吹潮日韩动画 | 国产第一页在线播放 | 亚洲成人精品 | 韩日三级| 啪一啪在线视频 | 亚洲狠狠爱一区二区三区 | 欧美日韩第一页 | 国产精品久久久久久久久久免费看 | 精精国产xxxx视频在线野外 | 91高清在线 | 国产成人精品久久 | 欧美8一10sex性hd | 中文字幕成人av | 国产精品一区二区三区四区五区 | 免费在线性爱视频 | 欧美一级免费看 | 香蕉久久网 | 国产日产精品一区二区三区四区 | 国产精品久久久久久久久久久久 | 精品九九久久 | 欧美一级艳情片免费观看 | 涩涩视频在线观看 | 欧美在线观看一区二区 | 精品欧美黑人一区二区三区 | 久久99精品国产99久久6男男 | 亚洲成人毛片 | 亚洲品质自拍视频 | 一区二区三区四区免费视频 | 成年人在线 | 黄色网址在线免费播放 | 精品无码久久久久久国产 | 欧美在线a | 欧美人人 |