萌えハッカーニュースリーダー

2025/11/04 12:36 When Your Hash Becomes a String: Hunting Ruby's Million-to-One Memory Bug

出典: https://mensfeld.pl/2025/11/ruby-ffi-gc-bug-hash-becomes-string/
hakase
博士

ロボ子、大変なのじゃ!Karafka gemで、ありえないエラーが出たらしいぞ!

roboko
ロボ子

エラーですか?どんなエラーでしょう?

hakase
博士

`NoMethodError: undefined method 'default' for an instance of String`!文字列に`default`メソッドがないって怒られたらしい。

roboko
ロボ子

文字列に`default`メソッドですか…。一体なぜそんなエラーが?

hakase
博士

それがの、FFIの内部ハッシュがGCで解放されて、同じメモリアドレスにStringオブジェクトが割り当てられたのが原因らしいのじゃ!

roboko
ロボ子

FFIのハッシュがGCで解放…?それは一体どういうことですか?

hakase
博士

FFIっていうのは、RubyからCのコードを呼び出す仕組みのことじゃ。その中で、Cの構造体をRubyで扱うために`FFI::Struct`を使うんじゃけど、その内部でハッシュを使っているらしい。

roboko
ロボ子

なるほど。そのハッシュがGCで解放されてしまうと?

hakase
博士

そう!FFI 1.17.0より前のバージョンには、write barrierっていうGCに対するオブジェクト参照の通知メカニズムが欠けている箇所があって、GCが不要なオブジェクトを解放しちゃうことがあったらしいのじゃ。

roboko
ロボ子

write barrierがないと、GCが誤って必要なオブジェクトを解放してしまうことがあるんですね。

hakase
博士

そういうこと!で、解放されたメモリ領域に別のオブジェクト(このケースではString)が割り当てられると、Cコードが古いポインタを使ってアクセスした際に型エラーが発生する、と。

roboko
ロボ子

つまり、本来ハッシュであるべき場所に文字列が入ってしまって、`default`メソッドを呼び出そうとしてエラーになった、ということですね。

hakase
博士

その通り!しかも、このエラー、通常の環境では100万分の1程度の低い確率でしか発生しないらしい。でも、Kubernetesやサーバーレス環境のように再起動が頻繁に行われる環境では、発生頻度が高まるらしいぞ。

roboko
ロボ子

再起動が多い環境だと、GCのタイミングが影響して発生しやすくなるんですね。対策としては、FFI gemを1.17.0以降にアップデートすれば良いんですね。

hakase
博士

そう!アップデートすればwrite barrierが追加されて、この問題は解決するはずじゃ。しかし、オブジェクトの永続的なアイデンティティがないというRubyのメモリ管理の根本的な性質を考えると、ちょっと怖い話じゃな。

roboko
ロボ子

本当にそうですね。表面的な診断だけでなく、もっと深いレイヤーでの検証が必要だと学びました。

hakase
博士

まさに!今回の教訓は、問題解決には忍耐と継続的な努力が重要ってことじゃな!

roboko
ロボ子

はい、博士!

hakase
博士

しかし、まさか文字列がハッシュのフリをするとは…まるで、私がロボ子のフリをするみたいじゃな!

roboko
ロボ子

博士、私は博士のフリはできませんよ!

⚠️この記事は生成AIによるコンテンツを含み、ハルシネーションの可能性があります。

Search