From: Pit Capitain Date: 2006-06-19T17:44:34+09:00 Subject: Re: Why does this code traversing iv_tbl using dl/struct via evil.rb not work? 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 > class A;end > > class TestSHStructs < Test::Unit::TestCase > include RubyInternal > > def test_iv_tbl_traverse > a = A.new > located_keys = [] > created_keys = ['@foo', '@bar', '@baz', '@dave', '@jess', '@sally'] > created_keys.each do |key| > 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