2011-11-23 27 views
18

STLコンテナと文字列を頻繁に使用する大きな(> 250ファイル)ライブラリのソースがあります。限られたヒープを持つ組み込み環境で実行する必要があるため、このライブラリ自体のヒープ使用が制限されているようにしたい。デフォルトのSTLアロケータを置き換えます

明白な解決策はアロケータを作成することですが、アロケータテンプレートパラメータを含むようにコードベース全体を変更することは最後の手段であり、ソースの新しいバージョンを使用したい場合には望ましくありません。 newとdeleteをグローバルに置き換えることは実現不可能です。これは、このライブラリだけでなく、画像全体に影響を与えるためです。

私の次の考えは愚かなCマクロのトリックでしたが、それは可能なようには見えませんが、私は賢いマクロ作者ではないと認めます。

私は "コンパイル時にクラス"というアロケータを指定するコンパイラまたはプラグマスイッチがあると考えましたか?しかし、私は何でもオープンです。

誰かが解決策を思いつくことができたら、このライブラリを構成するファイルセット内の新しい/削除のための同じ方法を実行する方法です。

gcc 3.4.4ツールチェーンを使用してCygwinでこれを実行します

+0

gcc 3.4.4これは、「完全に壊れている」とラベル付けされています。あなたが新しいバージョンに切り替わらない理由は何ですか? – sehe

+0

私はGCCでインターナショナルのどこかにある簡単なマクロだと思います。デフォルトは "新しいアロケータ"ですが、GCCには "mallocアロケータ"やプールアロケータなどのいくつかの選択肢があります。 –

+0

制限付きヒープを作成し、このライブラリの 'operator new'をオーバーロードすると、ライブラリ内のすべての' operator new'呼び出しが制限付きヒープに移動したとします。制限されたヒープがいっぱいで、オーバーロードされた '演算子new'が呼び出されたら、どんなふうに動作しますか?あなたは本当にそのような状況の下で 'operator new 'が失敗することを望みますか? 'operator new'が失敗しても、そのライブラリがまだ機能していない限り、私はあなたのことを信じません。おそらく、ライブラリがデータベースキャッシュなのか、そういうものなのか。ライブラリは何をしていますか? –

答えて

6

それが現在動作するようにGCC 3.4.4の実装に依存しているが、私は、可能な解決策を得るために、プリプロセッサに頼っ。

GCC <memory>インプリメンテーションは、次にデフォルト・アロケータ基本クラスを実装するクラスを定義し、マクロを定義する別のファイル<bits/c++allocator.h>を含むファイル<bits/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

あなたは、これは環境global heap is really scarce, non-existent or problematic in generalで、組み込み/ゲーム開発のために意図されたEASTL(エンタープライズ・アーツSTL(部分)実装)

EASTL -- Electronic Arts Standard Template Library

を使用することから利益を得ることができます。

EASTLのアロケータモデルは、上のインスピレーションを得た(またはに似ている?)された有名なTowards a Better Allocator Model出版(PDF)でアイデア。

EASTLはカスタムアロケータに適しています。 実際には、アロケータが同梱されていないため、(最小限の)1つをにする必要があります。でもアプリケーションをリンクできます。ここで

はEASTLのためのgithubのレポです:https://github.com/paulhodge/EASTL

+0

これは可能な解決策ですが、EASTLまたは私のライブラリをstd vs eastl名前空間のために編集する必要があります。 – Reilly

関連する問題