Subject:
[ruby-ffi] Re: AutoPointer on an array of structs corrupts the structs values
From:
Wayne Meissner
Date:
3/26/13 8:53 AM
To:
ruby-ffi@googlegroups.com

Its not exactly corrupting the memory, it is just that when you access the second, etc element of the array, it is stepping by 1 byte, instead of GTop::MemoryMapEntry.size.

Its a bug, but since it is broken on both MRI and JRuby, you'll need to do a work-around.

Instead of this:
    ssi = GTop::MemoryMapEntry.new(ss_pointer[i])

use:
    ssi = GTop::MemoryMapEntry.new(ss_pointer + (i * GTop::MemoryMapEntry.size))


On Tuesday, 26 March 2013 10:23:47 UTC+10, Maurizio De Santis wrote:
Hello,

I have an issue using FFI::AutoPointer on an array of structs.

This is the C function declaration:

glibtop_map_entry * glibtop_get_proc_map (glibtop_proc_map *buf, pid_t pid);

The returned value is an array of glibtop_map_entry structs should be freed using g_free .

If I declare the pointer to the array of structs entries using FFI::Pointer, everything works fine, and the output of the structs is correct:


s = GTop::ProcessMemoryMaps.new
addr = GTop.process_memory_maps(s, Process.pid)
ss_pointer = FFI::Pointer.new(GTop::MemoryMapEntry, addr)
s[:number].times do |i|
  ssi = GTop::MemoryMapEntry.new(ss_pointer[i])
  p Hash[ ssi.members.map { |m| [ m, ssi[m].is_a?(FFI::StructLayout::CharArray) ? ssi[m].to_s.force_encoding('UTF-8') : ssi[m] ] } ]
end
GTop::GLib.g_free ss_pointer



This is a part the ouput:


{:flags=>8191, :start=>140496509870080, :end=>140496510115840, :offset=>0, :perm=>21, :inode=>2494196, :device=>2054, :size=>245760, :rss=>8192, :shared_clean=>8192, :shared_dirty=>0, :private_clean=>0, :private_dirty=>0, :filename=>"/lib/x86_64-linux-gnu/libpcre.so.3.13.1"}
{:flags=>8191, :start=>140496510115840, :end=>140496512208896, :offset=>245760, :perm=>16, :inode=>2494196, :device=>2054, :size=>2093056, :rss=>0, :shared_clean=>0, :shared_dirty=>0, :private_clean=>0, :private_dirty=>0, :filename=>"/lib/x86_64-linux-gnu/libpcre.so.3.13.1"}
{:flags=>8191, :start=>140496512208896, :end=>140496512212992, :offset=>241664, :perm=>17, :inode=>2494196, :device=>2054, :size=>4096, :rss=>4096, :shared_clean=>0, :shared_dirty=>0, :private_clean=>0, :private_dirty=>4096, :filename=>"/lib/x86_64-linux-gnu/libpcre.so.3.13.1"}
[...]
{:flags=>8191, :start=>140496599904256, :end=>140496620888064, :offset=>0, :perm=>19, :inode=>0, :device=>0, :size=>20983808, :rss=>20844544, :shared_clean=>0, :shared_dirty=>0, :private_clean=>0, :private_dirty=>20844544, :filename=>"[heap]"}
{:flags=>8191, :start=>140737331818496, :end=>140737331953664, :offset=>0, :perm=>19, :inode=>0, :device=>0, :size=>139264, :rss=>49152, :shared_clean=>0, :shared_dirty=>0, :private_clean=>0, :private_dirty=>49152, :filename=>"[stack]"}
{:flags=>8191, :start=>140737332150272, :end=>140737332154368, :offset=>0, :perm=>21, :inode=>0, :device=>0, :size=>4096, :rss=>4096, :shared_clean=>4096, :shared_dirty=>0, :private_clean=>0, :private_dirty=>0, :filename=>"[vdso]"}
{:flags=>8191, :start=>18446744073699065856, :end=>18446744073699069952, :offset=>0, :perm=>21, :inode=>0, :device=>0, :size=>4096, :rss=>0, :shared_clean=>0, :shared_dirty=>0, :private_clean=>0, :private_dirty=>0, :filename=>"[vsyscall]"}



However, when I use FFI::AutoPointer:


s = GTop::ProcessMemoryMaps.new
addr = GTop.process_memory_maps(s, Process.pid)
pre_ss_pointer = FFI::Pointer.new(GTop::MemoryMapEntry, addr)
ss_pointer = FFI::AutoPointer.new pre_ss_pointer, GTop::GLib.method(:g_free)
s[:number].times do |i|
  ssi = GTop::MemoryMapEntry.new(ss_pointer[i])
  p Hash[ ssi.members.map { |m| [ m, ssi[m].is_a?(FFI::StructLayout::CharArray) ? ssi[m].to_s.force_encoding('UTF-8') : ssi[m] ] } ]
end



the output is corrupted:


{:flags=>8191, :start=>140185021132800, :end=>140185021378560, :offset=>0, :perm=>21, :inode=>2494196, :device=>2054, :size=>245760, :rss=>8192, :shared_clean=>8192, :shared_dirty=>0, :private_clean=>0, :private_dirty=>0, :filename=>"/lib/x86_64-linux-gnu/libpcre.so.3.13.1"}
{:flags=>31, :start=>547597738800, :end=>547597739760, :offset=>1513209474796486656, :perm=>17582052945254416384, :inode=>432345564227577358, :device=>8, :size=>960, :rss=>32, :shared_clean=>32, :shared_dirty=>0, :private_clean=>0, :private_dirty=>3386706919782612992, :filename=>"lib/x86_64-linux-gnu/libpcre.so.3.13.1"}
[...]
{:flags=>0, :start=>1376256, :end=>163459629056, :offset=>134610944, :perm=>16106127360, :inode=>536870912, :device=>536870912, :size=>0, :rss=>0, :shared_clean=>0, :shared_dirty=>8660248813382860800, :private_clean=>7596496373740942904, :private_dirty=>3419760881481315694, :filename=>"libpcre.so.3.13.1"}
{:flags=>0, :start=>5376, :end=>638514176, :offset=>525824, :perm=>62914560, :inode=>2097152, :device=>2097152, :size=>0, :rss=>0, :shared_clean=>0, :shared_dirty=>4069054363051241216, :private_clean=>7956009158131998518, :private_dirty=>7795578597039503477, :filename=>"ibpcre.so.3.13.1"}
{:flags=>0, :start=>21, :end=>2494196, :offset=>2054, :perm=>245760, :inode=>8192, :device=>8192, :size=>0, :rss=>0, :shared_clean=>0, :shared_dirty=>3907004821653777455, :private_clean=>8461816663211521631, :private_dirty=>7596498852877118840, :filename=>"bpcre.so.3.13.1"}
[...]
{:flags=>3543826231318490725, :start=>3223091, :end=>0, :offset=>0, :perm=>0, :inode=>0, :device=>0, :size=>0, :rss=>0, :shared_clean=>0, :shared_dirty=>0, :private_clean=>0, :private_dirty=>0, :filename=>""}
{:flags=>3688780367150412590, :start=>12590, :end=>0, :offset=>0, :perm=>0, :inode=>0, :device=>0, :size=>0, :rss=>0, :shared_clean=>0, :shared_dirty=>0, :private_clean=>0, :private_dirty=>0, :filename=>""}
{:flags=>3329058624053866355, :start=>49, :end=>0, :offset=>0, :perm=>0, :inode=>0, :device=>0, :size=>0, :rss=>0, :shared_clean=>0, :shared_dirty=>0, :private_clean=>0, :private_dirty=>0, :filename=>""}
{:flags=>3543826243108679279, :start=>0, :end=>0, :offset=>0, :perm=>0, :inode=>0, :device=>0, :size=>0, :rss=>0, :shared_clean=>0, :shared_dirty=>0, :private_clean=>0, :private_dirty=>0, :filename=>""}
{:flags=>13843071262143278, :start=>0, :end=>0, :offset=>0, :perm=>0, :inode=>0, :device=>0, :size=>0, :rss=>0, :shared_clean=>0, :shared_dirty=>0, :private_clean=>0, :private_dirty=>0, :filename=>""}
{:flags=>54074497117747, :start=>0, :end=>0, :offset=>0, :perm=>0, :inode=>0, :device=>0, :size=>0, :rss=>0, :shared_clean=>0, :shared_dirty=>0, :private_clean=>0, :private_dirty=>0, :filename=>""}
{:flags=>211228504366, :start=>0, :end=>0, :offset=>0, :perm=>0, :inode=>0, :device=>0, :size=>0, :rss=>0, :shared_clean=>0, :shared_dirty=>0, :private_clean=>0, :private_dirty=>0, :filename=>""}
{:flags=>825111345, :start=>0, :end=>0, :offset=>0, :perm=>0, :inode=>0, :device=>0, :size=>0, :rss=>0, :shared_clean=>0, :shared_dirty=>0, :private_clean=>0, :private_dirty=>0, :filename=>""}
{:flags=>3223091, :start=>0, :end=>0, :offset=>0, :perm=>0, :inode=>0, :device=>0, :size=>0, :rss=>0, :shared_clean=>0, :shared_dirty=>0, :private_clean=>0, :private_dirty=>0, :filename=>""}
{:flags=>12590, :start=>0, :end=>0, :offset=>0, :perm=>0, :inode=>0, :device=>0, :size=>0, :rss=>0, :shared_clean=>0, :shared_dirty=>0, :private_clean=>0, :private_dirty=>0, :filename=>""}


As you can see, the struct values "get chewed" from entry to entry.

Is it a known issue?

--
 
---
You received this message because you are subscribed to the Google Groups "ruby-ffi" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ruby-ffi+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.