ruby - object_id 分配如何工作?

标签 ruby internals

我正在研究 Ruby 的 .object_id 并注意到,在 irb 的几个连续 session 中,我得到了这些相同的结果:

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

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

另一方面,给定字符串的 object_id 在退出并重新运行 irb 后不再相同。

这给我提出了几个问题:

  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,依此类推。

最佳答案

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

但是出于性能原因true , false , nilFixnum s是经过特殊处理的。对于这些对象,内存中实际上没有包含对象数据的结构。对象的所有数据都编码在 VALUE 中本身。正如您已经计算出 false 的值一样, true , nil和任何 Fixnum i , 是 0 , 2 , 4i*2+1分别。

之所以可行,是因为在运行 MRI 的任何系统上,0 , 2 , 4i*2+1永远不会是堆上对象的有效地址,因此与指向对象数据的指针没有重叠。

关于ruby - object_id 分配如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3430280/

相关文章:

ruby-on-rails - rails : Returning errors from Module to Rake task?

javascript - JavaScript 中的事件处理程序是否以 FIFO、LIFO 或并行方式触发一个事件?

python - 什么时候在 Python 的 AST 中使用 ExtSlice 节点?

c - 地址转换示例

memory - 哪种 channel 类型在 Go 中使用最少的内存?

ruby - 清除输入字段并使用 Watir 输入新信息? ( ruby ,瓦蒂尔)

ruby - Ruby 中的 Project Euler #6(有什么区别?)

ruby - 我可以初始化一个在 ruby​​ 中休眠的线程吗?

xml - 对 SVG 的 Ruby 支持

python - python 中 1 + 1 可以等于 3 吗?