Category : [ C/C++/PG Tips ]
Date : 2004年11月19日 12:55
Next :
太字の意味。 (2004年11月19日 17:47)
Prev :
STL人間 (2004年11月19日 02:33)
前にDLLでSTL使うとおかしくなる、と言う話をしたことがあるが
どうもこれは相性でもなんでもなくて、ちゃんとした理由があるようだ。
調べてみたところ、どうもDLLとEXE間でまたがってメモリの確保、
開放、拡張等を行うとメモリアクセス保護違反が発生するらしい。
まぁ、よくよく過去の経験を思い出してみれば、
DLLとEXE間っていろいろと制限があったような気がする。
(昔VBやってるときに色々苦しめられた記憶がある)
で、STLはどうもDLL化した時DLLとEXE間でまたがって
メモリ確保等の操作を行ってしまうらしい。
と言ってもそれはSTLがクソとかそういう話じゃなくて
仕方ないことのようだ。
STLはテンプレートライブラリである。更にインライン展開される。(*1)
で、これをDLLのクラス内のメンバ変数として使ったどうなるか。
どうもこれがテンプレートであることやインライン展開であるところの絡みで
メモリ確保等の処理がまたがってしまうようである。
なるほど。MGLをDLL化した時に出ていた警告メッセージは
どうもこれを意味していたようだ・・・。
ここからは、DLLとEXE間の事を良く知らない(更にテンプレート、
インライン展開のことも良く知らない)のであくまで憶測になるが…
クラスと言うものはあくまで型である。
よって、構造体のようにメンバ変数自体はEXE上のメモリに配置される。
しかし、そのクラスのメソッド自体はDLL上のメモリに配置される。
通常のクラスのメンバ変数ならばEXE上でインスタンスが生成され、
EXE上で開放されるだろう。構造体と同じように。
そして、DLL上のメソッドからアクセスされたとしても
これは何ら問題ではない。
しかし、STLを使用した場合、恐らくDLL上のメソッド上にて
vector.push_back()のようにSTLのメモリを拡張等行うことがあるはずだ。
そうするとどうなるか。
そう。メモリアクセス保護違反だ。
恐らく、こういうメカニズムでDLLにてSTLを使った場合、
アプリが落ちる結果となる。
しかし、バリバリC++でコードを組んでいる人間として、
STLを使えなくなると言うことはかなり痛い。出来れば使いたいものである。
ではどうすれば良いのか…?
以下対処法。
クラスのメンバ変数としてSTLを持つと、
インスタンス化した時一緒にEXE側でSTLのインスタンスも作られてしまう。
こうなると、DLL側(*2)からメモリの拡張等の操作が行えなくなってしまうので、
STLのインスタンス生成はDLL側で行う。
つまり、クラスのメンバ変数として持つのはSTL"へのポインタ"であり、
インスタンス自体はDLL側のコンストラクタ辺りでnewないしalloc等をする。
(もちろん開放も忘れずに)
こうすれば、STLのメモリ操作が全てDLL内のみで完結し、
メモリアクセス保護違反も無くなる。
クラスなのにメンバ変数のインスタンスが完全に隠蔽されている所が
まるでCOMインターフェースのようだ、と思うかもしれないが、
それはCOMインターフェースからヒントを得たので当然である。(笑
そして実際、このやり方に直してみたところ、
メモリアクセス保護違反は無くなり上手く動いてくれた。
COMインターフェースが何故オブジェクトのインスタンスを隠蔽しているのか
少し理解出来たような気分になれた瞬間である(笑
*1 : テンプレートがインラインに展開される、
と言う意味かも知れないが詳しくは知らない。
おかげで汎用性があり、更に高速なライブラリな訳であるが、
その反面、こう言った問題点も多く発生してしまう訳である。
*2 : てかこれ.cpp側って言った方が分かりやすいですかね。
Trackback URL : http://www.nwhite.info/mt/trbk_haruhi.xcg/820