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 永远不会相同。
这给我提出了几个问题:
- 是否存在确定某些
object_id
的已知方案?其他的基本都是随机的吗? - true、false 和 nil 的 id 不是连续的。有没有办法询问给定的 id 代表什么对象? (我很好奇其他个位数和 id 与什么相关。)
- 您可以(不是说您应该)编写混淆的 Ruby,其中使用已知的对象 id 来引用对象而不命名它们,例如“id 201 + 的对象” id 19 的对象”表示“100 + 9”?
更新
使用Andrew Grimm的建议,我尝试发现其他“低id”对象,但发现:
- 此序列中似乎没有任何偶数对象 - id 6、8、10等不指向任何事物。
- 正如我之前的实验所暗示的,所有奇数编号的 id 都属于数字。具体来说,id 1 指向数字0,3 指向1,5 指向2,依此类推。
I'm playing around with Ruby's .object_id
and noticed that, in several sequential sessions of irb, I get these identical results:
false.object_id // 0
true.object_id // 2
nil.object_id // 4
100.object_id // 201
In fact, every integer's object_id seems to be ((value * 2) + 1).
On the other hand, a given string's object_id is never the same after exiting and re-running irb.
This raises several questions for me:
- Is there a known scheme by which certain
object_id
s are determined? Are others basically random? - The ids for true, false, and nil, aren't sequential. Is there a way to ask what object is represented by a given id? (I'm curious what the other single-digit and ids are tied to.)
- Could you (not that you should) write obfuscated Ruby where you use known object ids to refer to objects without naming them, like "object of id 201 + object of id 19" to mean "100 + 9"?
Update
Using Andrew Grimm's suggestion, I tried discovering other "low id" objects, but found that:
- There don't appear to be any more even-numbered objects in this sequence - ids 6, 8, 10, etc don't point to anything.
- As implied by my earlier experiment, all the odd-numbered ids belong to numbers. Specifically, id 1 points to the number 0, 3 points to 1, 5 points to 2, and so forth.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在 MRI 中,对象的
object_id
与 C 级别上表示对象的VALUE
相同。对于大多数类型的对象,此VALUE
是指向内存中存储实际对象数据的位置的指针。显然,这在多次运行期间会有所不同,因为它仅取决于系统决定分配内存的位置,而不取决于对象本身的任何属性。然而,出于性能原因,
true
、false
、nil
和Fixnum
会被特殊处理。对于这些对象,内存中实际上不存在包含对象数据的结构。对象的所有数据都编码在VALUE
本身中。正如您已经计算出false
、true
、nil
和任何Fixnum
i
的值一样code> 分别是0
、2
、4
和i*2+1
。其有效的原因是,在任何运行 MRI 的系统上,
0
、2
、4
和i*2+1
永远不是堆上对象的有效地址,因此与指向对象数据的指针没有重叠。In MRI the
object_id
of an object is the same as theVALUE
that represents the object on the C level. For most kinds of objects thisVALUE
is a pointer to a location in memory where the actual object data is stored. Obviously this will be different during multiple runs because it only depends on where the system decided to allocate the memory, not on any property of the object itself.However for performance reasons
true
,false
,nil
andFixnum
s are handled specially. For these objects there isn't actually a struct with the object's data in memory. All of the object's data is encoded in theVALUE
itself. As you already figured out the values forfalse
,true
,nil
and anyFixnum
i
, are0
,2
,4
andi*2+1
respectively.The reason that this works is that on any systems that MRI runs on,
0
,2
,4
andi*2+1
are never valid addresses for an object on the heap, so there's no overlap with pointers to object data.分配整数
(value * 2) + 1
和非整数(x * 2)
类似于 希尔伯特大酒店悖论,描述了如何将无限多的客人分配到无限的酒店。关于通过 ID 查找对象,有
ObjectSpace._id2ref(object_id)
。除非您的实现没有 ObjectSpace。Assigning Integer
(value * 2) + 1
and non-integers(x * 2)
is analogous to Hilbert's paradox of the Grand Hotel, which describes how to assign infinitely more guests to an infinite hotel.With regards to finding objects by their ID, there's
ObjectSpace._id2ref(object_id)
. Unless your implementation doesn't have ObjectSpace.