2011-09-18 63 views
3

當我超載newdelete實現我自己的小物件/線程安全的分配器。新主場迎戰的malloc,超載新

問題是,當我超載new,我不能使用new而不破壞通用因果關係或至少編譯器。我發現的大多數例子在new被超載,使用Malloc()來做實際的分配。但從我對C++的理解來看,根本沒有Malloc()的用例。

多個答案與此類似,一些較少侵權的SO外:In what cases do I use malloc vs new?

我的問題,是怎麼做的我重載運營商new當不使用Malloc()分配的實際內存?

(這是出於好奇比什麼都重要,儘量不要超載背後的推理過於認真,我有一個單獨的問題出在該anywho!)

+0

聽起來像一個很難回答的問題,因爲我想不出任何其他方式分配C++中的內存無(直接)調用'new'或'malloc()'?我誤解了什麼? – Mysticial

+0

@Mysticial - 我不這麼認爲!我想我們都會發現是否有辦法或不夠快。 :P –

+0

當然,我忘記了操作系統特定的內存分配器......:) – Mysticial

回答

4

簡短的回答:如果你不想現有的malloc,你需要實現你自己的堆管理器

一個堆管理器,例如Linux中的glibc中的malloc,Windows中的HeapAlloc是用戶級別的算法。首先,請記住,堆已針對分配小尺寸對象(如4〜512字節)進行了優化。

如何實現自己的堆管理器?至少,您必須調用一個在您的進程中分配內存塊的系統API。 Windows有VirtualAlloc,Linux有sbrk。這些API分配一大塊內存,但大小必須是大小的倍數。通常,x86和Windows/Linux中的頁面大小爲4KB。

獲得頁面的一大塊後,你需要實現自己的算法如何這個大內存砍掉成更小的請求。一個經典的(仍然非常實用)的實現和算法是dlmallochttp://g.oswego.edu/dl/html/malloc.html

要實現,你需要有幾個數據結構的簿記和一些優化策略。例如,對於像16,20,36,256字節這樣的小對象,堆管理器會維護每個大小的塊列表。所以,有一個列表清單。如果請求的尺寸大於頁面尺寸,則只需撥打VirtualAllocsbrk即可。但是,有效的實施非常具有挑戰性。您不僅要考慮速度和空間開銷,還要緩存局部性和碎片。

如果你有興趣在多線程環境優化的堆管理器,看看一個tcmallochttp://goog-perftools.sourceforge.net/doc/tcmalloc.html

+0

哦整齊!當然,它依賴於操作系統,但我想這就是重載'new'開始的成本。謝謝! –

+0

在這種情況下依賴於OS是不可避免的,但它是微不足道的。您只需爲虛擬內存分配API進行抽象函數調用即可。一個簡單的#ifdef也可以(請參閱dlmalloc源代碼)。 – minjang

3

我看到在調用malloc()的一個新的重載內部沒有問題,只要確保你重載刪除,因此調用自由()。但如果你真的不想調用malloc(),一個辦法是隻分配足夠的內存的另一種方式:

class A { 
    public: 
     /* ... */ 
     static void* operator new (size_t size) { 
      return (void *)new unsigned char[size]; 
     } 
     static void operator delete (void *p) { 
      delete[]((unsigned char *)p); 
     } 
     /* ... */ 
}; 
+0

這只是委託給全局新建/刪除,這是如果你甚至沒有實現這兩個功能會自動發生的。我是否錯過了某些有用的東西? – wjl

+2

@wjl是的,它只是委託給全局的new/delete,但是因爲他在問題中提到它是一個小對象線程安全分配器,他可以改變這個例子(它只是說明他如何分配內存)並實現緩存或他需要的任何東西。 – fbafelipe

相關問題