开发者

Accessing objects memory address in ruby..?

开发者 https://www.devze.com 2022-12-22 01:58 出处:网络
Is there any way in Ruby to get the memory address of objects? (i = 5) Is it possible to get the开发者_开发知识库 memory address of that object 5?

Is there any way in Ruby to get the memory address of objects?

(i = 5)

Is it possible to get the开发者_开发知识库 memory address of that object 5?

I have been trying to get this over some time.


Yes.

From "Fiddling with Ruby’s Fiddle":

"You can get the actual pointer value of an object by taking the object id, and doing a bitwise shift to the left. This will give you the pointer (or memory location) of the ruby object in memory."

Using your example of i = 5 it could be done like so:

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

"In Ruby, why does inspect() print out some kind of object id which is different from what object_id() gives?" has more info about object_id, including a brief introduction to the C source underlying the implementation which you might find helpful.

Take a look at "Fiddle" for some other cool things you can do.


Ruby Memory Validator should be able to pull that off but it's not free.

Aman Gupta patched Joe Damatos memprof but it seems to be a work in progress and I never got it to run on my machine. Joe has a couple of really good posts about memprof and other low level stuff on his blog.

Now I'm not so sure they really can. Integers are stored as a Fixnum and Fixnum is not a usual Ruby object, it just looks that way. Ruby uses a clever speed up trick with the object_id to make Fixnum objects immidiate values. The number is in fact stored in the object_id itself. That's why two different Fixnum containing the same value has the same object_id.

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

The object_id of a Fixnum is actually created by bit shifting to the left and then setting the least significant bit.

5 is 0b101 and the object_id for 5 is 11 and 11 in binary is 0b1011.

4711 is 0b0001001001100111, shift left and set the bit and you get 0b0010010011001111 and that is 9423 which happens to be the object_id for z above.

This behaviour is most probably implementation specific but I don't know of a Ruby implementation that doesn't handle Fixnum this way.

There are at least three more immediate objects in Ruby and that's false, true and nil.

>> false.object_id
=> 0
>> true.object_id
=> 2
>> nil.object_id
=> 4


I don't know of a way of having the exact address, but maybe you're looking for something like the object_id method?

Extract from its documentation

Returns an integer identifier for obj.
The same number will be returned on all calls to id for a given object, and no two active objects will share an id


Example:

> 5.object_id
=> 11
> true.object_id
=> 2


Ruby Memory Validator does give you the memory address for the object.

Joe Damato's work (http://timetobleed.com/plugging-ruby-memory-leaks-heapstack-dump-patches-to-help-take-out-the-trash) and (http://timetobleed.com/memprof-a-ruby-level-memory-profiler) is based on the work Software Verification did to create a Ruby memory inspection API (http://www.softwareverify.com/ruby/customBuild/index.html).

Joe describes that on his blog. Therefore Joe's work should also return the appropriate addresses. I'm not fully up to speed with the latest version of Joe's work - he only told me about the first version, not the latest version, but nonetheless, if you are tracking memory allocations in the underpinnings of Ruby, you are tracking the addresses of the objects that hold whatever it is you are allocating.

That doesn't mean you can dereference the address and read the data value you expect to find at that address. Dereferencing the address will point you to the internals of a basic Ruby Object. Ruby objects are a basic object which then store additional data alongside, so knowing the actual address is not very useful unless you are writing a tool like Ruby Memory Validator or memprof.

How do I know the above about Ruby Memory Validator and the API we released? I designed Ruby Memory Validator. I also wrote the assembly language bits that intercept the Ruby calls that allocate the memory.


What exactly are you trying to do?

Keep in mind that a Ruby object is not directly analogous to a variable in a language like C or C++. For example:

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

Even through a and b are separate variables, they are references to the same underlying data and have the same object_id.

If you find yourself needing to take the address of a variable, there is probably an easier approach to whatever you are trying to do.


Since you indicated (buried in a comment somewhere) that you're really just trying to understand how Ruby references things, I think things work as follows:

A VALUE in Ruby's C api represents an object (a nil, a FixNum or a Boolean) or a pointer to an Object. The VALUE contains a 3 bit tag indicating which of these it is, and contains the value (for the first 3) or a direct memory pointer (for an Object). There's no way to get at the VALUE directly in Ruby, (I'm not sure if the object_id is the same or different.)

Note that JRuby operates differently.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号