トップ «前の日記(2010-08-13) 最新 次の日記(2010-08-15)» 編集

日々の破片

Subscribe with livedoor Reader
著作一覧

2010-08-14

_ Ruby拡張ライブラリと、RubyのMSVCRTバージョン違いまとめ

Ruby拡張ライブラリと、Ruby、それからRuby拡張ライブラリが依拠するDLLの3つのプレイヤーがいる場合に、Rubyが落ちる場合と落ちない場合がある。

通常、まずいのは次の組み合わせだ。

RubyがリンクしたMSVCRTと拡張ライブラリがリンクしたMSVCRTが異なる。

これは、mallocとfreeのMSVCRTの実装による。

・もしかすると、MSVCRT70以降は共通化されているかも知れないが未確認。

・理屈上で確認しているのは、MSVCRT(6)とそれ以降の任意の1つとの組み合わせ

これは、次の状況で発生する(追記あり)。

・拡張ライブラリでマクロを利用してオブジェクトを生成する(具体的にはData_Make_Struct)。マクロなのでmallocの呼び出しは拡張ライブラリ側のMSVCRTで行う。

・GCで上記オブジェクトを回収。GCのfreeなのでRuby側のMSVCRT側で行う

それに対して、拡張ライブラリが利用するサードパーティDLLはRubyオブジェクトを利用することはないので、よほど生なAPI(mallocしたオブジェクトを返すのでfreeは呼び出し側でやってくれ、というようなもので、しかもWin32APIではなくMSVCRTのmallocを利用する)が無ければ問題ない。

のだが、readlineのMSVCRT(6)が、rubyとreadline.soをMSVCRT(100)で利用すると落ちるのだった。

で、なんでだか追っかけたら、fdの問題だった。うむ。そう来たか。

というか、メモリーアロケーションにしろ、ファイルハンドルにしろ、なぜ素のWin32のオブジェクトを使わないのかと(それは、POSIXそっくりさんのMSVCRTと、Win32の設計思想の相違をMSVCRTが吸収しているからだと言えばそれまでなのだが)

追記:

と思っていたのだが、今見ると、ALLOCはxmallocで、xmallocはgc.cのruby_xmallocだから、拡張ライブラリとRuby本体で異なるmallocを使うということは無いようだな。

ということで、上のは、ファイル関係以外は嘘っぱちということだ。

本日のツッコミ(全10件) [ツッコミを入れる]
_ なかだ (2010-08-14 22:46)

一番ありがちなのはerrnoとか

_ arton (2010-08-14 23:33)

ああ、確かに。昔々、winsock.hで、#define errno get_errno() /*正確かどうかはわからない*/ というのを見たけど、変数の参照はその通りですね。

_ なかだ (2010-08-15 00:23)

errnoについてはもう少々複雑というかもう一段階挟まってて、MSVCRT内で使うTLSに取られてるわけですが、そのTLSのためのインデックスがバージョンごとに別なのでerrnoも別になってるという状態です。<br>というか、VCはコンパイラ自身がTLSをサポートしてるはずなので、素直にそっちを使っててくれれば問題なかったんじゃないかと。

_ arton (2010-08-15 01:22)

そんなことになっているとは。<br>(ちょっと見てみる)__flsindexと__tlsindexで別管理だからってことかな。これをすべてのDLLで共有するとしたらTlsAllocの戻り値をシェアできる領域にコピーしておく必要があるけど、MSVCRTの段階でtlsindexをシェアしないようにしているから既に遅かったということでは(VC10にはdefファイルが入っていないから現在はどうかわからないけど)。

_ arton (2010-08-15 01:33)

>VCはコンパイラ自身がTLSをサポートしてるはず<br>これって、__declspec(thread) int errno; という意味?

_ なかだ (2010-08-15 07:59)

そういう意味。どのバージョンからサポートしたのか分からないけど。

_ arton (2010-08-15 09:26)

VC6ではサポート済みでしたね(仕事で使ったので覚えてる)。でも、これもDLL単位になりそうな。

_ なかだ (2010-08-15 16:13)

あぁなるほど、dllexportにはできないというわけか。<br>確かに、特定のsegmentに対するoffsetだと、DLLが複数になったら解決できないな。

_ なかむら(う) (2010-08-15 18:58)

少なくともVC6にはありましたねえ。<br>とりあえずこのURLは見ておくといいかな。特に一番下の項とか必見。<br>http://msdn.microsoft.com/en-us/library/2s9wt68x.aspx

_ arton (2010-08-15 23:38)

これって、Vista以前は、DLLでは事実上declspecディレクティブは使えないって意味なのかな? と思ったが、暗黙のうちにリンカに解決(アプリケーションロード時に動的にロード)されればOKってことか。つまりRubyの拡張ライブラリではTlsAllocしなければだめということか(tlsを使うのがあるかどうかは微妙な気がするけど)


2003|06|07|08|09|10|11|12|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|

ジェズイットを見習え