2012-12-03 16 views
6

私は最近、アロケータの複数のインスタンス間で共有されるメモリプールに基づいてカスタムアロケータを開発しています。STLコンテナ、SBOとカスタムアロケータの競合

意図は、アロケータはSTLおよび標準Cと互換性があるということでした++などなど

ベクトル、両端キュー、マップ、文字列としてベースのコンテナは、しかし、特に何かが私にいくつかの混乱を引き起こしました。 std :: vector,std :: stringのようなコンテナのさまざまな実装では、小さなバッファの最適化 - 小さな初期メモリ要件のためのスタックベースの割り当てを使用します。たとえば、MSVC9.1については

はのbasic_stringクラスに次のメンバーがあります。

union _Bxty 
{ // storage for small buffer or pointer to larger one 
    _Elem _Buf[_BUF_SIZE]; 
    _Elem *_Ptr; 
    char _Alias[_BUF_SIZE]; // to permit aliasing 
} _Bx; 

は、私がこのような容器をインスタンス化する際に1だけに実装 を丸めると常に提供アロケータを使用する方法を見ることができないが SBOは使用しません。 カスタムアロケータを実装する意図の1つが、共有メモリの量が のコンテキストで使用できるようになったためです。例えば

私はSTD二 インスタンス::多分より小さいかSBO上部 限界に等しいメモリの共通ブロック を共有するプロセスごと文字列いずれかを持つことができる状況を持っていると思います。

おそらく関連:May std::vector make use of small buffer optimization?

typedef std::vector<int,mysharedmemallocator> shmvtype; 

shmvtype v(2,0); //<-- if SBO then error as memory is allocated on 
       //stack not via the allocator 

v[1] = 1234; //<-- if SBO then error as wrong piece of memory 
       // is being modified. 

はオーバー何人かの人々のために物事を複雑に思えるとして共有メモリに基づいていない別の例を見てみましょう。私は私のstd :: basic_stringやstd :: vectorなどを特化したいとします。アロケータは、0xABで割り当てられたメモリを塗りつぶすアロケータを持っています。

この新しいアロケータに特化しているがSBOも使用するコンテナは、0xABパターンでいっぱいになったSBOベースのメモリを持ちません。例えばだから:カスタムアロケータを実装する意向の

typedef std::basic_string<char,myfillmemallocator> stype 

stype s; 
s.resize(2); 

assert(s[0] == 0xAB); // if SBO this will fail. 

答えて

4

1これは、あなたがそれをどうするつもり何かもしれ

共有メモリコンテキストでそれらを使用できるようにしましたが、それは彼らが存在する理由ではありません。実際には、C++ 98/03のbasic_stringを除いて、オブジェクト間に共有メモリを割り当てても、は合法ではありません。彼らはアロケータオブジェクトを共有することができるので、同じ場所からメモリを取得することができます。しかし、1つのオブジェクトの変更が無関係の別のオブジェクトに影響を与えることは違法です。各インスタンスは別々にする必要があります。

コピーオンライト文字列は、システムが文字への非constアクセスであればそれに書き込みを行い、コピーを実行すると仮定しているためにのみ機能します。そしてC++ 11では、basic_stringさえもこのようなコピーオンスタイルのものを禁止しています。

たとえば、プロセスごとに1つのstd :: stringインスタンスが2つあり、共通のメモリブロックを共有する状況があります。これはSBOの上限より小さいか等しいことがあります。

独自のクラスを作成しないとできません。アロケータは、メモリがどこから来るかを制御するだけです。あなたが望んでいるのは、コピーオンライト文字列または何らかの共有文字列クラスです。

この目的のために特別に設計されたコンテナクラスが必要です。

+1

コメントありがとうございますが、ちょうど1つの質問ですが、共有メモリを割り当てるアロケータを持つことはできませんし、オフセットポインタのコンセプトを使ってメモリをエイリアスすることもできます - これは通常どおりに行われます(boost.interprocess)確かに私はそれができない理由を理解しています。 –

+2

@セミナー:その文字列をコピーするとどうなりますか?その文字列に文字を挿入すると、再割り当てが発生する可能性があります。これらの操作のセマンティクスがどのようなものであるべきかは明確ではありませんが、セマンティクスが何であっても、実装自体が知る必要があるセマンティクスです。つまり、特定の方法で動作する特定のコンテナ実装が必要です。 –

+1

共有文字列から別の文字列へのコピーは共通のコピーですが、ターゲット文字列は共有メモリを持つことは期待できません。これは他の方法でも同じです。通常のstd :: stringからコピーします特別なアロケータによって提供される共有メモリに格納されます - これは、Resize/Append et alに関する質問 –

関連する問題