Доступ к объектам памяти по адресу в рубине ..? - PullRequest
14 голосов
/ 08 марта 2010

Есть ли способ в ruby ​​получить адрес памяти объектов ..

скажем ..

(i = 5) возможно ли получить адрес памяти этого объекта 5 ..

Я пытался получить это в течение некоторого времени ..,

Любой ответ был бы очень признателен ...

спасибо,

С уважением, Левирг

Ответы [ 6 ]

13 голосов
/ 06 июня 2014

Да.

Из " Возиться с скрипкой Руби ":

"Фактическое значение указателя объекта можно получить, взяв идентификатор объекта и выполнив битовое смещение влево. Это даст вам указатель (или ячейку памяти) объекта ruby ​​в памяти."

Используя ваш пример i = 5, это можно сделать так:

i = 5
i_ptr_int = i.object_id << 1
=> 22

" Почему в Ruby inspect () выводит какой-то идентификатор объекта, который отличается от того, что дает object_id ()? ", имеет дополнительную информацию о object_id, включая краткое введение в Источник C, лежащий в основе реализации, который может оказаться полезным.

Взгляните на " Fiddle ", чтобы узнать о некоторых других интересных вещах, которые вы можете сделать.

8 голосов
/ 08 марта 2010

Ruby Memory Validator должен быть в состоянии осуществить это, но это не бесплатно.

Аман Гупта исправлен Джо Даматос memprof но, похоже, это работа в процессе , и я так и не смог запустить ее на своей машине. У Джо есть несколько действительно хороших сообщений о memprof и других материалах низкого уровня в его блоге .

Теперь я не уверен, что они действительно могут. Целые числа хранятся как Fixnum, а Fixnum не является обычным объектом Ruby, это выглядит просто так. Ruby использует хитрый трюк ускорения с object_id, чтобы заставить Fixnum объекты иммидизировать значения. Номер фактически хранится в самом object_id. Вот почему два разных Fixnum, содержащие одно и то же значение, имеют одинаковые object_id.

>> x=5
=> 5
>> y=5
=> 5
>> x.object_id
=> 11
>> y.object_id
=> 11
>> z=4711
=> 4711
>> z.object_id
=> 9423

object_id из Fixnum фактически создается путем смещения бита влево и затем установки младшего значащего бита.

5 равно 0b101, а object_id для 5 равно 11 и 11 в двоичном виде равно 0b1011.

4711 равно 0b0001001001100111, сдвиньте влево и установите бит, и вы получите 0b0010010011001111, а это 9423, что на z выше *1043*.

Такое поведение , скорее всего, зависит от конкретной реализации, но я не знаю реализации Ruby, которая не обрабатывает Fixnum таким образом.

В Ruby есть еще как минимум три непосредственных объекта, это false, true и nil.

>> false.object_id
=> 0
>> true.object_id
=> 2
>> nil.object_id
=> 4
5 голосов
/ 08 марта 2010

Я не знаю, как получить точный адрес, но, может быть, вы ищете что-то вроде object_id метода?

Выписка из его документации

Возвращает целочисленный идентификатор для obj.
Один и тот же номер будет возвращен при всех вызовах идентификатора для данного объекта, и никакие два активных объекта не будут иметь идентификатор


Пример:

> 5.object_id
=> 11
> true.object_id
=> 2
1 голос
/ 10 марта 2010

Ruby Memory Validator дает вам адрес памяти для объекта.

Работа Джо Дамато (http://timetobleed.com/plugging-ruby-memory-leaks-heapstack-dump-patches-to-help-take-out-the-trash) и (http://timetobleed.com/memprof-a-ruby-level-memory-profiler)) основана на работе, выполненной верификацией программного обеспечения для создания API проверки памяти в Ruby (http://www.softwareverify.com/ruby/customBuild/index.html).

Джо описывает это в своем блоге. Поэтому работа Джо также должна возвращать соответствующие адреса. Я не совсем в курсе последней версии работы Джо - он рассказал мне только о первой версии, а не о последней, но, тем не менее, если вы отслеживаете выделение памяти в основе Ruby, вы отслеживаете адреса объектов, которые содержат то, что вы выделяете.

Это не значит, что вы можете разыменовать адрес и прочитать значение данных, которое вы ожидаете найти по этому адресу. Разыменование адреса приведет вас к внутренним элементам базового объекта Ruby. Объекты Ruby являются базовыми объектами, которые затем хранят дополнительные данные вместе, поэтому знание фактического адреса не очень полезно, если вы не пишете такой инструмент, как Ruby Memory Validator или memprof.

Как мне узнать выше о Ruby Memory Validator и API, который мы выпустили? Я разработал Ruby Memory Validator. Я также написал биты ассемблера, которые перехватывают вызовы Ruby, выделяющие память.

0 голосов
/ 18 марта 2010

Поскольку вы указали (где-то в комментарии), что действительно пытаетесь понять, как Ruby ссылается на вещи, я думаю, что все работает следующим образом:

A VALUE в C api в Ruby представляет объект (nil, FixNum или Boolean) или указатель на Object. VALUE содержит 3-битный тег, указывающий, какой из них это, и содержит значение (для первых 3) или прямой указатель памяти (для Object). Нет никакого способа добраться до VALUE непосредственно в Ruby, (я не уверен, что object_id - это то же самое или другое.)

Обратите внимание, что JRuby работает по-другому.

0 голосов
/ 08 марта 2010

Что именно вы пытаетесь сделать?

Имейте в виду, что объект Ruby не является прямым аналогом переменной в языке, подобном C или C ++. Например:

a = "foo"
b = a
b[2] = 'b'
b
  => "fob"
a
  => "fob"
a == b
  => true
a.object_id
  => 23924940
b.object_id
  => 23924940
a.object_id == b.object_id
  => true

Даже через a и b это отдельные переменные, они являются ссылками на одни и те же базовые данные и имеют одинаковые object_id.

Если вам понадобится взять адрес переменной, возможно, существует более простой подход к тому, что вы пытаетесь сделать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...