C C 記憶體管理器

2021-09-07 19:40:16 字數 2842 閱讀 2477

c標準庫提供了malloc,free,calloc,realloc,c++標準庫還提供了new, new, delete, delete。這些用來管理記憶體,看起來夠用了,為啥還要自己寫乙個記憶體管理器呢?

原因還是從效能考慮:例如malloc和new是出於通用性考慮的,能處理多執行緒情況(multithread)。對於單執行緒的程式,這種額外的功能反而降低效能。

而且還注意到,new/delete/free/malloc都是要在user-space和kernel-code做切換的,context的切換會降低效能。如果自己寫乙個user-land的記憶體管理器,就能大幅減少這種切換。還有就是gc(garbage collection)。

速度:比編譯器的記憶體分配器要快才行

魯棒:不能有記憶體洩漏,分配多少就收回多少

方便:使用者不怎麼需要改**,就能把記憶體管理器加進去

移植:應當跨平台,使用者在啥系統上都能用,方便移植

申請大塊記憶體

一次性申請一大塊記憶體,減少向系統申請的次數,以後需要申請記憶體就從這一大塊上分配。

(這不就是快取麼。。)

為特定尺寸優化

任何程式中都一種最常見的記憶體申請尺寸。為這種尺寸優化,提公升效能。

需要刪除的記憶體暫時存放在容器中(敝帚自珍)

從使用者角度看,變數宣告週期結束,要釋放分配的記憶體;但是記憶體管理器實際上可以「不真的把這塊記憶體還給系統」,而是攢起來留給後續需要分配記憶體時用。當然,這種記憶體更多的是碎片,所以再分配時可能不夠用,那就得再找大塊記憶體去分配了。

首先是乙個不使用記憶體管理器的**,記憶體的申請和釋放是手動完成的,並且放在for迴圈中,來頻繁的申請和釋放,方法這種做法的效果(慢啊)。**:

#include #include using namespace std;

class complex

private:

double r; //實部

double c; //虛部};

int main(int argc, char* ar**)

for (int j=0;j<1000;j++)

}t2 = clock();

cout << double(t2-t1)/clocks_per_sec << "s" << endl;

return 0;

}

這次用乙個記憶體管理類來託管記憶體的申請和釋放,並且原有的complex類上僅僅是過載了new/delete/new/delete這四個operator。放碼過來:

#include #include using namespace std;

class imemorymanager;

class memorymanager: public imemorymanager

~memorymanager()

void* allocate(size_t);

void free(void*);

private:

struct freestore;

void expandpoolsize();

void cleanup();

freestore* freestorehead;

};memorymanager gmemorymanager;

class complex

inline void* operator new(size_t size)

inline void operator delete(void* object)

inline void* operator new(size_t size)

inline void operator delete(void* object)

private:

double r;

double c;

};void* memorymanager::allocate(size_t size)

freestore* head = freestorehead;

freestorehead = head->next;

return head;

}void memorymanager::free(void* object)

const int poolsize = 128;

void memorymanager::expandpoolsize()

head->next = 0;

}void memorymanager::cleanup()

}int main(int argc, char* ar**)

for (int j=0;j<1000;j++)

}

t2 = clock();

cout << double(t2-t1)/clocks_per_sec << "s" << endl;

return 0;

}

時間開銷對比

g++ main_v1.cpp -o main_v1 -o3

./main_v1

0.217214s

g++ main_v2.cpp -o main_v2 -o3

./main_v2

0.026611s

兩者的時間開銷竟然相差乙個數量級。

**的正確性

其實new()申請記憶體的**很不嚴謹,沒有檢查形參size是否會超過預設poolsize大小,只不過通常情況下單次的size肯定小於poolsize,但是極端情況下,或者一口氣申請了多個變數的記憶體,可能會越界。另外,只適用於單執行緒。

以上內容來自ibm的一篇教程,還有很多內容沒能看完和理解,挖坑帶填:

opencv記憶體管理器1

1.opencv使用記憶體儲存器memory storage 來統一管理各種動態物件的記憶體,在底層被實現為乙個有許多 相同大小的記憶體塊組成的雙向鍊錶,opencv可以快速的分配記憶體給內部儲存器。以下是常用的操作內部儲存器 的函式。2.序列是記憶體儲存器中的可以儲存的一種物件,openc中序列c...

C 程式設計記憶體管理器(記憶體池)

c語言中的標準庫函式malloc free calloc和realloc,以及c 中的new new delete和delete 操作符,是這兩種語言中記憶體管理的關鍵之處。注意一下c語言裡面的是函式,在c 裡面是操作符,這個據說在面試裡面被問到過。在執行時,malloc和new將向作業系統核心請求...

任務管理器測試記憶體洩露

用任務管理器測試記憶體洩露的方法很簡單。任務管理器和記憶體洩露緊密相關的只有兩項,乙個是記憶體使用率,乙個是當前控制代碼數。方法分別如下 1,記憶體洩露的方法 開啟任務管理器,此時要減少電腦或虛擬機器上其它型別的活動程式,盡量保證檢視到的引數和當前執行的程式有較大的相關性。記錄此時的記憶體使用率。在...