红宝石-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永远不会相同。

这给我提出了几个问题:

  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 1指向数字0,3指向1,5指向2,依此类推。
Nathan Long asked 2020-07-31T01:35:42Z
2个解决方案
63 votes

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

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

起作用的原因是,在运行MRI的任何系统上,024i*2+1都不是堆上对象的有效地址,因此与对象数据的指针不会重叠。

sepp2k answered 2020-07-31T01:36:31Z
31 votes

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

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

Andrew Grimm answered 2020-07-31T01:36:56Z
translate from https://stackoverflow.com:/questions/3430280/how-does-object-id-assignment-work