2011-11-23 112 views
18

我有大量使用STL容器和字符串的大型(> 250個文件)庫的源代碼。我需要在一個有限的堆的嵌入式環境中運行它,所以我想確保這個庫本身在堆的使用上受到限制。替換默認的STL分配器

顯而易見的解決方案是創建一個分配器,但修改整個代碼庫以包含分配器模板參數是最後一招,而且如果我想要採用新版本的源代碼,這是不可取的。全局替換新的和刪除是不可行的,因爲它會影響整個圖像,而不僅僅是這個庫。

我的下一個想法是愚蠢的C代碼宏伎倆,但似乎並不像它會是可能的,雖然我承認我不是一個聰明的宏作者。

所以我想「有沒有編譯器或編譯開關來指定分配<>在編譯時類」?但我對任何事情都是開放的。

下一個問題我要問,如果有人能拿出一個解決方案,是怎麼做的新的同/設定包括這個庫文件中刪除。

我用gcc 3.4.4工具鏈在Cygwin下運行它,用的VxWorks的目標,如果火花任何想法。

+0

gcc 3.4.4這已經足夠老了,被標記爲「完全破碎」。任何你不換用新版本的原因? – sehe

+0

我認爲在GCC中,這只是一個簡單的宏,在內部應該可以切換。默認是「新的分配器」,但GCC帶有幾個選擇,比如「malloc分配器」和池分配器等等。 –

+0

假設你可以創建一個有限的堆,然後只爲這個庫重載'operator new',所以庫中的所有'operator new'調用都會進入你有限的堆。當有限的堆滿了並且調用了重載的'operator new'時,你想要什麼樣的行爲?你真的想在這種情況下讓'operator new'失敗嗎?我不相信你會這樣,除非這個庫在'operator new'失敗時仍然可以運行。也許如果庫是一個數據庫緩存,或類似的東西。圖書館做什麼? –

回答

6

我使出了預處理得到一個可能的解決方案,雖然它目前依賴於GCC 3.4.4執行工作。

GCC <memory>實現包括文件<bits/allocator.h>,該文件又包含另一個文件<bits/c++allocator.h>,該文件定義了一個宏,該宏定義了實現默認分配器基類的類。

因爲在依賴於平臺的路徑/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/i686-pc-cygwin/bits中找到,所以我不覺得(非常)會用我自己的「依賴於平臺」的實現取代它。

因此,我只是在我的源代碼的包含路徑的根目錄下創建一個文件夾bits/,然後在該文件夾中創建文件c++allocator.h。我將需要的宏定義爲我的分配器類的名稱,它的作用就像一個魅力,因爲在搜索系統包含之前,gcc搜索我的包含路徑。

感謝您的回覆。我想我可以使用這個「解決方案」,只要我使用3.4.4,這個解決方案就可以工作。

+0

關於如何在Visual Studio中執行此操作的任何想法?我試圖找到默認的分配器頭文件,但迷路了:)謝謝! – OSH

3

所以我想「編譯時是否有編譯器或編譯指示開關指定 >分配器<>類?但我對任何事情都是開放的。

不,沒有。

看看here

分配器是每個stl容器中的模板參數。你需要改變它們。在處理嵌入式工作時,我曾經做過同樣的事情。我可以給你一些指針,如果你喜歡:

基本模板分配:

namespace PFM_MEM { 
    template <class T> 
    class CTestInstAllocator { 
    public: 
     // type definitions 
     typedef size_t size_type; 
     typedef ptrdiff_t difference_type; 
     typedef T*  pointer; 
     typedef const T* const_pointer; 
     typedef T&  reference; 
     typedef const T& const_reference; 
     typedef T   value_type; 

     // rebind CTestInstAllocator to type U 
     template <class U> 
     struct rebind { 
      typedef CTestInstAllocator<U> other; 
     }; 

     // return address of values 
     pointer address (reference value) const { 
      return &value; 
     } 
     const_pointer address (const_reference value) const { 
      return &value; 
     } 

     /* constructors and destructor 
     * - nothing to do because the CTestInstAllocator has no state 
     */ 
     CTestInstAllocator() { 
     } 
     CTestInstAllocator(const CTestInstAllocator&) { 
     } 
     template <class U> 
     CTestInstAllocator (const CTestInstAllocator<U>&) { 
     } 
     ~CTestInstAllocator() { 
     } 

     // return maximum number of elements that can be allocated 
     size_type max_size() const { 
      return std::numeric_limits<size_t>::max()/sizeof(T); 
     } 

     // pvAllocate but don't initialize num elements of type T by using our own memory manager 
     pointer allocate (size_type num) { 
      /** 
      * pvAllocate memory custom memory allocation scheme 
      */ 
      return(pointer)(CPfmTestInstMemManager::pvAllocate(num*sizeof(T))); 
     } 
     // initialize elements of allocated storage p with value value 
     void construct (pointer p, const T& value) { 
      // initialize memory with placement new 
      new((void*)p)T(value); 
     } 

     // destroy elements of initialized storage p 
     void destroy (pointer p) { 
      // destroy objects by calling their destructor 
      p->~T(); 
     } 
     // vDeallocate storage p of deleted elements 
     void deallocate (pointer p, size_type num) { 
      /** 
      *Deallocate memory with custom memory deallocation scheme 
      */ 
      CPfmTestInstMemManager::vDeallocate((void*)p); 
     } 
    }; 

    // return that all specializations of this CTestInstAllocator are interchangeable 
    template <class T1, class T2> 
    bool operator== (const CTestInstAllocator<T1>&, 
     const CTestInstAllocator<T2>&) { 
      return true; 
    } 
    template <class T1, class T2> 
    bool operator!= (const CTestInstAllocator<T1>&, 
     const CTestInstAllocator<T2>&) { 
      return false; 
    } 
} 

要特別注意,在這些線路:

/** 
* pvAllocate memory custom memory allocation scheme 
*/ 
return(pointer)(CPfmTestInstMemManager::pvAllocate(num*sizeof(T))); 

// vDeallocate storage p of deleted elements 
void deallocate (pointer p, size_type num) { 
/** 
*Deallocate memory with custom memory deallocation scheme 
*/ 
CPfmTestInstMemManager::vDeallocate((void*)p); 

在這裏你打電話新的地方並刪除堆中的哪些工作。

我可以爲您提供如何構建一些基本的內存管理器,以進一步幫助你舉個例子。

+0

所以你說沒有辦法告訴STL全局使用自定義分配器;您必須確保在使用stl類型時使用自定義分配器來定義它。對? – OSH

+0

@OrenS。那麼對於特定的編譯器來說,可能有一種選擇,但我只是從我的經驗談起。我和OP在同一個位置,必須這樣做。編輯更正的答案。 – FailedDev

+0

@FailedDev,我在這裏發佈之前看過那個頁面,並且很有希望。如果我能弄清楚如何讓我的任意分配器成爲一個'擴展'分配器,那我就是金。我也不知道該怎麼做。如果你知道,我會給我的下一隻狗命名爲「FailedDev」... – Reilly

6

你可以受益於使用EASTL(企業藝術STL(部分)實現)

EASTL -- Electronic Arts Standard Template Library

這是適用於嵌入式/遊戲開發,在環境中global heap is really scarce, non-existent or problematic in general

EASTL的分配器型號受到啓發(或類似於?)着名的Towards a Better Allocator Model出版物(PDF)中的想法。

EASTL適合自定義分配器。 事實上,它沒有附帶分配器,所以提供(最小)一個是需要甚至讓你的應用程序鏈接。

這裏是EASTL GitHub的回購:https://github.com/paulhodge/EASTL

+0

這是一個可能的解決方案,但由於std vs eastl命名空間,我必須編輯EASTL或我的庫。 – Reilly