web-dev-qa-db-ja.com

object_idの割り当てはどのように機能しますか?

Rubyの.object_idで遊んでいると、irbのいくつかの連続したセッションで、次のような同じ結果が得られることに気付きました。

false.object_id // 0
true.object_id // 2
nil.object_id // 4
100.object_id // 201

実際、すべての整数のobject_idは((value * 2)+ 1)のようです。

一方、irbを終了して再実行した後、特定の文字列のobject_idが同じになることはありません。

これは私にいくつかの質問を提起します:

  1. 特定のobject_idを決定するための既知のスキームはありますか?他は基本的にランダムですか?
  2. True、false、nilのIDは連続していません。特定のIDで表されるオブジェクトを確認する方法はありますか? (他の1桁の数字とIDが何に関連付けられているか知りたいです。)
  3. 難読化されたRubyを使用して、オブジェクトに名前を付けずにオブジェクトを参照する場合、「ID201のオブジェクト+ ID19のオブジェクト」は「100」を意味します。 + 9 "?

更新

Andrew Grimmの提案を使用して、他の「低ID」オブジェクトを見つけようとしましたが、次のことがわかりました。

  • このシーケンスにはこれ以上偶数のオブジェクトはないようです。ID6、8、10などは何も指していません。
  • 以前の実験で暗示されているように、すべての奇数IDは数値に属しています。具体的には、id 1は0を指し、3は1を指し、5は2を指します。
45
Nathan Long

MRIでは、オブジェクトのobject_idは、経営幹部レベルでオブジェクトを表すVALUEと同じです。ほとんどの種類のオブジェクトでは、このVALUEは、実際のオブジェクトデータが格納されるメモリ内の場所へのポインターです。オブジェクト自体のプロパティではなく、システムがメモリを割り当てることを決定した場所にのみ依存するため、これは複数の実行中に明らかに異なります。

ただし、パフォーマンス上の理由から、truefalsenil、およびFixnumsは特別に処理されます。これらのオブジェクトの場合、実際には、オブジェクトのデータをメモリに持つ構造体はありません。オブジェクトのすべてのデータは、VALUE自体にエンコードされます。 falsetruenilおよびFixnumiの値はすでに理解しているので、0、それぞれ24i*2+1

これが機能する理由は、MRIが実行されるすべてのシステムで、024およびi*2+1がヒープ上のオブジェクトに対して有効なアドレスになることはないためです。オブジェクトデータへのポインタとの重複はありません。

63
sepp2k

整数_(value * 2) + 1_と非整数_(x * 2)_の割り当ては、 ヒルベルトのグランドホテルのパラドックス に類似しており、無限に多くのゲストを無限のホテルに割り当てる方法を説明しています。

IDによるオブジェクトの検索に関しては、ObjectSpace._id2ref(object_id)があります。実装にObjectSpaceがない場合を除きます。

32
Andrew Grimm