Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why object_id persists on windows while not on linux?

This program

class ObjectGarden
    class << self.clone
            puts self.object_id
    end
end

puts ObjectGarden.clone.object_id

When run on Linux (have tested on RHEL) generates distinct object_ids across multiple runs as I had expected. However when I run it on Windows, I get same output across multiple runs. And no matter what I do (hibernate/shutdown/"infamous blue screen" and restart) object_ids won't change.

I also notice that object_id on Windows changes iff I change the content (even an insignificant change like add a new line or comment) of the program.

Why is this difference between Windows and Linux implementations? And since I don't have access to OS X can someone please run it on a Mac and document the result.

I'm using Ruby 1.9.2-p136 on Windows and Ruby 1.9.2-p180 on Linux.

like image 821
saihgala Avatar asked Nov 16 '12 12:11

saihgala


1 Answers

For most objects in ruby, the number you get from #object_id is actually the pointer to the internal C data structure for the object. This data structure in turn has space allocated for it by whatever memory allocator the ruby implementation/build uses.

Without reading code, I will guess that the linux version is producing different results every time because something, either ruby or the C allocator, is intentionally using a random offset for allocations or pointers, to make them hard to guess and thus make the program more secure.

There is only one guarantee that ruby will make about object_id's: as long as a particular object exists, its object_id will be unique to that ruby interpreter and will not change. That's all. You can even get the same object_id for an object as one that was created previously and later garbage collected, if it ends up getting the same chunk of memory.

Note also, if you do something like this:

irb(main):001:0> a = "hi"
=> "hi"
irb(main):002:0> a.object_id
=> 14348380
irb(main):003:0> a = a + " there"
=> "hi there"
irb(main):004:0> a.object_id
=> 14197020

The line a = a + " there" actually creates a new object, with a new object_id, where as using #concat doesn't:

irb(main):005:0> a = "hi"
=> "hi"
irb(main):006:0> a.object_id
=> 12031400
irb(main):007:0> a.concat " there"
=> "hi there"
irb(main):008:0> a.object_id
=> 12031400

Note also that in ruby, assignment binds the assigned variable to the object, so assigning one variable to another points them both at the same object:

irb(main):011:0> a = "hi"
=> "hi"
irb(main):012:0> a.object_id
=> 12081640
irb(main):013:0> b = a
=> "hi"
irb(main):014:0> b.object_id
=> 12081640

So changing one variable will change the other:

irb(main):015:0> a.concat " there"
=> "hi there"
irb(main):016:0> b
=> "hi there"
like image 119
Michael Slade Avatar answered Oct 24 '22 18:10

Michael Slade