いろきゅうの(元)はてなダイアリー

はてなダイアリーから移行中…

プロセス間で動的メモリを共有したい

単純な変数であれば DLLを使えばできる わけですが、これでは最初から固定された量のメモリ領域しか扱えないわけです。 配列を確保したとしても限界がある。

それじゃー、STLvectorとか使って、動的にメモリを確保するようにしようぜー! という事になるわけです。 こんな感じ。

#pragma data_seg("share")
std::vector g_stlVect;
#pragma data_seg()

…ですが、これはできない模様。MSDNライブラリによると

プロセスを DLL にアタッチするたびに、オブジェクトのコンストラクタが呼び出されるからです

との事。つまり、g_stlVect のコンストラクタが呼ばれまくり。 DLLがロードされる度に無条件に初期化(?)。 こりゃ―まずいだろうと。

じゃー、こうするかーとか思いつきました。

#pragma data_seg("share")
typedef std::vector THogeVector;
BYTE g_acHogeVectorMemory[sizeof(THogeVector)] = {0};
THogeVector* g_pcHogeVector = NULL;
#pragma data_seg()

void InitOnce()
{
  // placement new
  g_pcHogeVector = new(g_acHogeVectorMemory) ThogeVector;
}

void UninitOnce()
{
  g_pcHogeVector->~vector();
}

共有メモリ空間を、vector用にキャストしてしまえと。 placement new で1回だけ vector用として再初期化(?)してあげれば、コンストラクタは1回で済むじゃないかー!

…とか思ったのですが、よくよく考えてみたら、vectorの中では new でメモリを確保しているわけですよ。 new したメモリ空間って、そのプロセスでしか有効じゃないじゃないですか。 …つまり、他のプロセスから g_pcHogeVector にアクセスしたら、(違うプロセスなので) ポインタの先が不正になるんじゃね? …と。

…アカンがな。 …実験してないけど、落ちるよコレ。多分。 さ〜てどうするかな〜 と。

今のところ、仕方ないので CreatFileMapping で共有メモリ空間を作成して、手動でメモリコピー等を行うしかないかなー とか考えてます。 ちょっとメンドイですけど、大量の値が正しく共有されれば、とりあえずは問題ないですから……。 負け組み感が若干ありますけれど…^^;

それとも、他に何かナイスな方法があったりするのかしら〜?

追記

別件で困ったことがあったので書き残し。

共有している変数へのアドレスを、共有空間のポインタ変数に保存しておくのは ダメらしい です。