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,記憶體洩露的方法 開啟任務管理器,此時要減少電腦或虛擬機器上其它型別的活動程式,盡量保證檢視到的引數和當前執行的程式有較大的相關性。記錄此時的記憶體使用率。在...