Object address in Ruby

Short version: The default inspect method for a class displays the address of an object. * How can I do this in my own inspect method?

* (To be clear, I want the 8-digit hexadecimal number that you usually get from inspect . I don't care about the actual memory address. I just call it the memory address because it looks like this: I know that Ruby is memory safe. )

Long version: I have two classes: Thing and ThingList . ThingList is a subclass of Array specifically designed to store Things. Due to the nature of Things and the way they are used in my program, Things have an @container instance variable that points to a ThingList that contains Thing .

It is possible that two things have exactly the same data. So when I debug an application, the only way I can reliably distinguish between two things is to use inspect , which displays their address. However, when I inspect a Thing , I get pages on the output pages, because inspect will recursively check @container , forcing it to check every Thing in the list as well!

All I need is the first part of this conclusion. How to write my own inspect method in Thing that will only display this?

 #<Thing:0xb7727704> 

EDIT: I just realized that to_s does just that. I have not noticed this before, because I have a custom to_s that provides human readable information about the object.

Suppose I cannot use to_s and that I have to write a custom inspect .

+4
source share
3 answers

You can get the address using object_id and multiply it by 2 * and display it in hex format using sprintf (aka % ):

 "#<Thing:0x%08x>" % (object_id * 2) 

Of course, if you only need a number to be unique, and do not care that it is the actual address, you can just leave * 2 .

* For reasons that you do not need to understand (which means: I do not understand them), object_id returns half the memory address of the object, so you need to multiply by 2 to get the actual address.

+10
source

It's impossible. There is no way in Ruby to get the memory address of an object, since Ruby is a memory-safe language that (by design) has no direct memory access methods. In fact, in many Ruby implementations, objects do not even have a memory address. And in most implementations that map objects directly to memory, the memory address potentially changes after each garbage collection.

The reason that using a memory address as an identifier in current versions of MRI and YARV accidentally works is because they have an implementation of a crappy garbage collector that never defragments memory. In all other implementations, there are garbage collectors that defragment the memory and thus move objects in memory, thereby changing their address.

If you bind your implementation to a memory address, your code will only work on slow implementations with crappy garbage collectors. Itโ€™s not even guaranteed that MRI and YARV will always have crappy garbage collectors, in fact, in both implementations the garbage collector has been identified as one of the main performance bottlenecks, and we can safely assume that there will be changes to garbage collectors. There are already some significant changes to the YARV garbage collector in SVN, which will be part of YARV 1.9.3 and YARV 2.0.

If you need an identifier for objects, use Object#object_id .

+1
source

Instead of subclassing Array, instances of your class can delegate one for the desired methods so that you do not inherit the overridden inspect method.

0
source

All Articles