C 設計乙個簡單記憶體池的全過程

2022-09-24 12:54:12 字數 2443 閱讀 9266

什麼是記憶體池???

通常我們用new或malloc來分配記憶體的話,由於申請的大小不確定,所以當頻繁的使用時會造成記憶體碎片和效率的降低。為了克服這種問題我們提出了記憶體池的概念。記憶體池是一種記憶體分配方式。記憶體池的優點就是可以有效的減少記憶體碎片化,分配記憶體更快速,減少記憶體洩漏等優點。

記憶體池是在真正使用記憶體之前,先申請分配乙個大的記憶體塊留作備用。當真正需要使用記憶體的時候,就從記憶體池中分配一塊記憶體使用,當使這塊用完了之後再還給記憶體池。若是記憶體塊不夠了就向記憶體再申請一塊大的記憶體塊。

可以看出這樣做有兩個好處:

1、由於向記憶體申請的記憶體塊都是比較大的,所以能夠降低外碎片問題。

2、一次性向記憶體申請一塊大的記憶體慢慢使用,避免了頻繁的向記憶體請求記憶體操作,提高記憶體分配的效率。

記憶體碎片化:

造成堆利用率很低的乙個主要原因就是記憶體碎片化。如果有未使用的儲存器,但是這塊儲存器不能用來滿足分配的請求,這時候就會產生記憶體碎片化問題。記憶體碎片化分為內部碎片和外部碎片。

內碎片:

內部碎片是指乙個已分配的塊比有效載荷大時發生的。(舉個栗子:假設以前分配了10個大小的位元組,現在只用了5個位元組,則剩下的5個位元組就會內碎片)。內部碎片的大小就是已經分配的塊的大小和他們的有效載荷之差的和。因此內部碎片取決於以前請求記憶體的模式和分配器實現的模式。

外碎片:   外部碎片就是當空閒的儲存器的和計起來足夠滿足乙個分配請求,但是沒有乙個單獨的空閒塊足夠大可以處理這個請求。外部碎片取決於以前的請求記憶體的模式和分配器的實現模式,還取決於於將來的記憶體請求模式。所以外部碎片難以量化。

下面介紹一種簡單的記憶體池,它是針對於某種物件實現的。 我們可以用乙個鍊錶實現這個記憶體池,鍊錶上的每個結點都是乙個物件池,如果我們需要申請空間的話,直接去記憶體池裡面申請空間,當用完之後再還給記憶體池。

記憶體池的設計主要包含三步:

1、初始化

在建立記憶體池的時候為記憶體池分配了一塊很大的記憶體,便於以後的使用。

2、分配記憶體

當需要記憶體的時候就去記憶體池裡面分配記憶體。

3、**記憶體

www.cppcns.com當從記憶體池裡面分配來的記憶體使用完畢之後,需要將這塊記憶體還給記憶體池。

設計上面這個記憶體池最重要的問題就是如何重複利用釋放回來的記憶體,讓利用率達到最高???

但是如果當物件的大小小於物件指標的時候,也就是乙個物件的空間存不下乙個指標的大小,這時候就不可避免的產生內碎片。   例如:為t型別物件開闢物件池,sizeof(t)

**實現:

#pragma once

#include

using namespace std;

//用鍊錶來實現記憶體池,每乙個結點都掛有一塊記憶體

template

class objectpool

~blocknode()

};protected:

size_t _countin; //當前結點的在用的計數

blocknode* _frist; //指向鍊錶的頭

blocknode* _last; //指向鍊錶的尾

size_t _maxnum; //記錄記憶體塊最大的容量

static size_t _itemsize; //單個物件的大小

t* _lastdelete; //指向最新釋放的那個物件的空間

public:

objectpool(size_t initnum = 32, size_t maxnum = 100000) //預設最開始記憶體塊有32個物件,乙個記憶體塊最大有maxnum個物件

:_countin(0)

, _maxnum(maxnum)

, _lastdelete(null)

~objectpool()

t* new() //分配記憶體

//判斷還有沒有已經分配的記憶體且還未使用,如果沒有記憶體的話就要再分配記憶體

if (_countin >= _last->_objnum) //大於等於表示沒有了,這時候就要分配記憶體了

//還有已經分配好的未被使用的記憶體

t* object =(t*)((char*)_last->_memory + _countin*_itemsize);

_countin++;

return new(object) t(); //將這塊空間用重定位new初始化一下

}void destory()

_frist = _last = null;

}void delete(t* object) //釋放記憶體

}protected:

static size_t getitemsize()

else

}};template

size_t objectpool::_itemsize =objectpool::getitemsize(); //類外初始化靜態變數_itemsize

總結

乙個網頁開啟的全過程

從使用者在瀏覽器輸入網域名稱開始,到web頁面載入完畢,這是乙個說複雜不複雜,說簡單不簡單的過程,下文暫且把這個過程稱作網頁載入過程。下面我將依靠自己的經驗,總結一下整個過程。如有錯漏,歡迎指正。閱讀本文需要讀者已有一定的計算機知識,了解tcp dns等。眾所周知,開啟乙個網頁的過程中,瀏覽器會因頁...

訪問乙個網頁的全過程

前言 訪問目標位址有兩種方式 使用目標ip位址訪問。由於ip位址是一堆數字不方便記憶,於是有了網域名稱這種字元型標識。使用網域名稱訪問。網域名稱解析就是網域名稱到ip位址的轉換過程,網域名稱的解析工作由dns伺服器完成。比如說訪問 baidu.com 1.如果是網域名稱,首先將網域名稱解析成ip 計...

乙個url載入的全過程

最近在進行前端面試方面的一些準備,遇到了乙個經典前端問題,乙個url從輸入到頁面載入中間到底發生了什麼,以前也認真想過這個問題,但是當時回答的都不全面,現在來好好總結一下 總體來說分為以下六個步驟 1 dns解析 2 tcp連線 3 傳送http請求 4 伺服器處理請求並返回http報文 5 瀏覽器...