Why does this code traversing iv_tbl using dl/struct via evi

Hi all,

I seem to have misunderstood some finer point of how the instance
variable tables work. Since for something like this I expect code
speaks louder than words, I have made a small test case using evil.rb
(to keep the file size down) available from:

http://rubyforge.org/cgi-bin/viewvc.cgi/evil/lib/evil.rb?
revision=1.44&root=evil

Unfortunately, due to some error I have made this test case does not
find all the instance variable keys. I’m sure some wizard out there
will easily spot my newbie mistake. Could someone please point out
where I’m going wrong by making this tiny test case work?

Many thanks,

Rob.

Rob Pitt schrieb:

I seem to have misunderstood some finer point of how the instance
variable tables work. (…) Could someone please point out where I’m
going wrong by making this tiny test case work?

Rob, I added the necessary changes to your code below:

require ‘evil’
require ‘test/unit’

module RubyInternal
ST_TABLE_BIN = struct [
“ST_TABLE_ENTRY *entry”
]
end

  a.instance_variable_set(key,1)
end
r_object = RObject.new(a.internal_ptr)
table = ST_TABLE.new(r_object.iv_tbl)
chain = 0
while chain < table.num_bins

replace the following line:

  table_entry = ST_TABLE_ENTRY.new(table.bins + (chain * DL::sizeof('P')))

with:

     table_bin = ST_TABLE_BIN.new(table.bins + (chain * 

DL::sizeof(‘P’)))
table_entry = table_bin.entry &&
ST_TABLE_ENTRY.new(table_bin.entry)

  while table_entry
    sym = table_entry.key.to_sym 
    located_keys << sym.to_s if sym && sym.to_s[0] == ?@
    table_entry = table_entry.next && ST_TABLE_ENTRY.new(table_entry.next)
  end
  chain += 1
end
assert_equal(created_keys.sort,located_keys.sort)

end
end

“table.bins” points to an array of “table.num_bins” pointers to table
entries. So

table.bins + (chain * DL::sizeof(‘P’))

isn’t the address of a table entry, but the address of a pointer to a
table
entry. In order to dereference these pointers, I added the ST_TABLE_BIN
struct
to your code.

Regards,
Pit