#113 √ resolved
Charles L

String instance variable issue

Reported by Charles L | November 9th, 2007 @ 10:54 PM | in 1.0

Basically instance variables are popping up where they shouldn't:

% cat test.rb
p a = 'asdf'
p b = 'asdf'
p c = 'qwerty'
p a.object_id
p b.object_id
p c.object_id
p b.instance_variable_get(:@x)
p a.instance_variable_set(:@x, 1)
p b.instance_variable_get(:@x)
p c.instance_variable_get(:@x)

contrast the second last line here:

% ruby test.rb
"asdf"
"asdf"
"qwerty"
-605836498
-605836518
-605836538
nil
1
nil
nil

with here:

"asdf"
"asdf"
"qwerty"
262165
262173
262181
nil
1
1
nil

So "b" has picked up "a"'s instance variable, though they are different objects. Thought it was some sort of shared literal optimization, but doesn't look to be the case

Assembly:
#line 1
push_literal 0
string_dup
set a:0
pop
push_literal 1
string_dup
set b:1
pop
push_literal 2
string_dup
set c:2
...

Comments and changes to this ticket

  • Eero Saynatkari

    Eero Saynatkari November 11th, 2007 @ 01:36 AM

    • → Milestone changed from “1.0 preview” to “1.0”
    • → State changed from “new” to “open”

    Strings are implemented Copy-on-Write and it might be that it only detects modifications to the string itself, not the String object.

  • Eero Saynatkari

    Eero Saynatkari November 11th, 2007 @ 01:37 AM

    Erm, ignore everything after "Strings are implemented COW".. THAT might still have something to do with this, though. This is only Strings you have noticed the behaviour in?

  • Charles L

    Charles L November 11th, 2007 @ 05:49 AM

    Yeah I wondered if it affects other objects, but it only seems to be strings so far. Eg, if you run this, the first 2 printed values will be 1:

    'asdf'.instance_variable_set(:@x, 1)
    p 'asdf'.instance_variable_get(:@x)
    
    class MyString < String
    end
    
    MyString.new('asdf').instance_variable_set(:@x, 1)
    p MyString.new('asdf').instance_variable_get(:@x)
    
    [].instance_variable_set(:@x, 1)
    p [].instance_variable_get(:@x)
    
    {}.instance_variable_set(:@x, 1)
    p({}.instance_variable_get(:@x))
    
    Object.new.instance_variable_set(:@x, 1)
    p(Object.new.instance_variable_get(:@x))
    

    Seems odd as you get different object ids, and i'd have thought the instance variables would be in the same struct that the object id refers to.

  • Charles L

    Charles L November 11th, 2007 @ 06:10 AM

    Looking into it a bit further - I think its to do with the way that external instance variables are handled. It looks as if "object_get_ivars" looks up the object in a hash in order to find its associated instance variables.

    Note that it doesn't affect [] though. In my tests, both "asdf" strings got the same hash from "object_hash_int", however, eg empty arrays (which also need external instance variables) get a different hash.

    Is there any reason why this can't use object_id to lookup instead?

  • Eero Saynatkari

    Eero Saynatkari January 8th, 2008 @ 11:07 PM

    • → State changed from “open” to “resolved”

    Looks like this has been fixed at some point. Closed.

Please Login or create a free account to add a new comment.

You can update this ticket by sending an email to from your email client. (help)

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

People watching this ticket