Подтвердить что ты не робот

Как работает назначение object_id?

Я играю с Ruby .object_id и заметил, что в нескольких последовательных сеансах irb я получаю эти одинаковые результаты:

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

Фактически, каждый целочисленный object_id представляется ((значение * 2) + 1).

С другой стороны, данная строка object_id никогда не будет прежней после выхода и повторного запуска irb.

Это вызывает несколько вопросов для меня:

  • Существует ли известная схема, в которой определены определенные object_id? Другие в основном случайны?
  • Иды для true, false и nil не являются последовательными. Есть ли способ спросить, какой объект представлен данным идентификатором? (Мне любопытно, к чему привязаны другие одиночные цифры и идентификаторы.)
  • Не могли бы вы (не то, чтобы вы должны) писать обфускацию Ruby, где вы используете известные идентификаторы объектов, чтобы ссылаться на объекты, не называя их, например, "объект id 201 + object of id 19" означает "100 + 9"?

Update

Используя предложение Andrew Grimm, я попытался открыть другие объекты с низким идентификатором, но обнаружил, что:

  • В этой последовательности больше нет четных объектов - идентификаторы 6, 8, 10 и т.д. не указывают ни на что.
  • Как явствует из моего предыдущего эксперимента, все нечетные иды принадлежат числам. В частности, id 1 указывает на число 0, 3 указывает на 1, 5 точек на 2 и т.д.
4b9b3361

Ответ 1

В MRI объект object_id объекта совпадает с VALUE, который представляет объект на уровне C. Для большинства типов объектов этот VALUE является указателем на местоположение в памяти, где хранятся фактические данные объекта. Очевидно, что это будет отличаться во время нескольких прогонов, потому что это зависит только от того, где система решила выделить память, а не на какое-либо свойство самого объекта.

Однако по соображениям производительности true, false, nil и Fixnum обрабатываются специально. Для этих объектов на самом деле нет структуры с данными объекта в памяти. Все данные объекта закодированы в самом VALUE. Поскольку вы уже определили значения для false, true, nil и любого Fixnum i, равны 0, 2, 4 и i*2+1 соответственно.

Причина, по которой это работает, заключается в том, что в любых системах, где работает MRI, 0, 2, 4 и i*2+1 никогда не являются действительными адресами для объекта в куче, поэтому нет совпадений с указателями для объектных данных.

Ответ 2

Назначение целых чисел (value * 2) + 1 и нецелых (x * 2) аналогично парадокс Гильберта Гранд-отеля, в котором описывается, как назначать бесконечно больше гостей в бесконечный отель.

Что касается поиска объектов по их идентификатору, то ObjectSpace._id2ref(object_id). Если ваша реализация не имеет ObjectSpace.