object_id赋值如何工作?

Nat*_*ong 43 ruby internals

我正在玩Ruby,.object_id并注意到,在irb的几个连续会话中,我得到了相同的结果:

false.object_id // 0
true.object_id // 2
nil.object_id // 4
100.object_id // 201
Run Code Online (Sandbox Code Playgroud)

实际上,每个整数的object_id似乎都是((value*2)+ 1).

另一方面,在退出并重新运行irb之后,给定字符串的object_id永远不会相同.

这为我提出了几个问题:

  1. 是否有已知的方案object_id确定某些s?其他人基本上是随机的
  2. true,false和nil的id不是顺序的.有没有办法询问给定id表示的对象是什么?(我很好奇其他一位数和ids的关系.)
  3. 你可以(不是你应该)编写模糊的Ruby,你使用已知的对象id引用对象而不命名它们,比如"id 201的对象+ id为19的对象"意味着"100 + 9"?

更新

使用Andrew Grimm的建议,我尝试发现其他"低id"对象,但发现:

  • 在这个序列中似乎没有任何更多的偶数对象 - ids 6,8,10等不指向任何东西.
  • 正如我之前的实验所暗示的那样,所有奇数编号的id都属于数字.具体地,id 1指向数字0,3指向1,5指向2,依此类推.

sep*_*p2k 63

在MRI中object_id,对象与VALUE表示C级对象的对象相同.对于大多数类型的对象,这VALUE是指向存储器中存储实际对象数据的位置的指针.显然,这在多次运行期间会有所不同,因为它仅取决于系统决定分配内存的位置,而不取决于对象本身的任何属性.

但是由于性能原因true,false,nilFixnums的特殊处理.对于这些对象,实际上并没有在内存中包含对象数据的结构.所有对象的数据都在VALUE自身编码.正如你已经想通了值false,true,nil和任何Fixnum i,是0,2,4i*2+1分别.

这个工作的原因是,在该MRI上运行的任何系统0,2,4并且i*2+1永远不会为堆上的对象的有效地址,所以有与指针对象数据没有重叠.

  • 符号似乎也有点特殊,它们的值太低而不能成为真正的地址..有谁知道内部结构? (2认同)

And*_*imm 31

分配整数(value * 2) + 1和非整数(x * 2)类似于希尔伯特大酒店的悖论,它描述了如何将无限多的客人分配给无限的酒店.

关于通过他们的ID查找对象,有ObjectSpace._id2ref(object_id).除非您的实现没有ObjectSpace.