タイトルのとおりです。
RubyからC言語を呼び出すFiddleライブラリでコールバック関数は Fiddle::Closure::BlockCaller
を使います。
Fiddle::Closure::BlockCaller.new(TYPE_INT, [TYPE_VOIDP, TYPE_VOIDP]){|x, y|
x.to_s(1) <=> y.to_s(1)
}
ところが、Fiddle::Closure::BlockCaller
はRubyのオブジェクトなので、気をつけないとガーベッジコレクションに回収されてしまいます。ガーベッジコレクションに回収されると、メモリが開放されてしまい、呼び出すことができなくなります。そしてSegmentation Faultが発生します。
Rubyでは関数の代わりにブロックがあります。ブロックを利用して、動的にFiddle::Closure::BlockCaller
のインスタンスを生成するということやりたくなるはずで、この際に注意してオブジェクトへの参照を残しておかないと、GCがせっかく生成した回収していきます。具体的には、レシーバのポインタのインスタンス変数にFiddle::Closure::BlockCaller
を追加してやるなどします。
普段Rubyを使う上で、GCやメモリ管理など考えないので、かなり注意していないと、この罠にはまります。
この記事は以上です。