Help us understand the problem. What is going on with this article?

FixnumとBignumとRubinius

More than 3 years have passed since last update.

Ruby向けのC拡張を書いている過程で、Rubiniusのバグらしきものを発見してしまいました。

FixnumとBignum

Rubyの整数は、メモリの続く限り大きな値を入れられるようになっています。ただ、整数演算が遅ければ言語としての使い勝手を大きく損なう事にもなります。

ということで、Rubyでは整数全般はIntegerという抽象クラスとして、実装は2つのクラスに分けています。

Fixnumは速度を重視した、小さな整数についての型です。以前に触れましたが、Ruby内部では実際にオブジェクトを用意せず、object_idと簡単に変換できるようになっています。Fixnumだと識別するためのビットが1ビット必要なので、32ビット環境では31ビット整数、64ビット環境では63ビット整数となっています1

Fixnumに入り切らないサイズの整数はBignumになります。内部的には多倍長整数と言って、値を細かく分けて保存しているのですが、メソッドなどはFixnumと共通なので、(速度が落ちることを除けば)Ruby上からは特に違いなく使えます。

ということで、Ruby上からは、よほどパフォーマンスにこだわるような場面を除いて、基本的にFixnumBignumを識別する必要はまず生じません。

一方、C言語からRubyの拡張ライブラリを書く場合、Fixnumはそのまま計算できるのに対して、Bignumは関数やメソッド経由で使うことになるなど、まったくの別物となります。正しくハンドリングしなければ、うまく動きません。

Rubiniusで起きたこと

作成中のGemのテストをCRuby、JRuby、Rubiniusで行っていたところ、妙な現象が生じました。

Cライブラリに突入する関係上、FixnumBignumの違いが出てくる場面だったので、両者の境界値をテストケースに入れてテストを回していました。

すると、Rubiniusだけエラーで止まってしまいました。調べてみると、

  1. -0x4000_0000_0000_0000という、本来ならFixnumとなるはずの整数リテラルがBignumとなっていた
  2. 負の数にビット反転をかけると、0x3fff_ffff_ffff_ffffとなり、こちらはFixnumになっていた
  3. Bignumの符号反転がFixnumになるという想定外の事態となり、TypeErrorで死亡

という流れでした。C言語レベルの世界なら別として、Ruby側に「Fixnumの範囲内に収まるBignum」が出現しているのはよろしくないので、Rubinius側にIssueを立てています


  1. Windowsでは(x64でも)longが32ビットなので、Fixnumは31ビットしかありません。 

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした