48

我正在玩 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是否存在确定某些 s的已知方案?其他的基本都是随机的吗?
  2. true、false 和 nil 的 id 不是连续的。有没有办法询问给定 id 代表什么对象?(我很好奇其他个位数和 ID 与什么相关联。)
  3. 你能(不是你应该)编写混淆的 Ruby,在其中使用已知的对象 ID 来引用对象而不命名它们,比如“id 201 的对象 + id 19 的对象”表示“100 + 9”?

更新

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

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

2 回答 2

66

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

然而,出于性能原因truefalse,nilFixnums 被特殊处理。对于这些对象,内存中实际上没有包含对象数据的结构。VALUE所有对象的数据都在其自身中编码。正如您已经计算出、和 any的值false,分别是、和。truenilFixnum i024i*2+1

这样做的原因是,在任何运行 MRI 的系统上,024并且i*2+1永远不是堆上对象的有效地址,因此与指向对象数据的指针没有重叠。

于 2010-08-07T12:47:44.743 回答
34

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

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

于 2010-08-07T12:01:47.860 回答