object_id 分配如何工作?

发布于 2024-09-13 16:19:19 字数 740 浏览 2 评论 0原文

我正在使用 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 代表什么对象? (我很好奇其他个位数和 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,依此类推。

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:

  1. Is there a known scheme by which certain object_ids are determined? Are others basically random?
  2. 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.)
  3. 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

孤单情人 2024-09-20 16:19:19

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

然而,出于性能原因,truefalsenilFixnum 会被特殊处理。对于这些对象,内存中实际上不存在包含对象数据的结构。对象的所有数据都编码在 VALUE 本身中。正如您已经计算出 falsetruenil 和任何 Fixnum i 的值一样code> 分别是 024i*2+1

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

In MRI the object_id of an object is the same as the VALUE that represents the object on the C level. For most kinds of objects this VALUE 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 and Fixnums 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 the VALUE itself. As you already figured out the values for false, true, nil and any Fixnum i, are 0, 2, 4 and i*2+1 respectively.

The reason that this works is that on any systems that MRI runs on, 0, 2, 4 and i*2+1 are never valid addresses for an object on the heap, so there's no overlap with pointers to object data.

风吹雪碎 2024-09-20 16:19:19

分配整数 (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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文