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 |
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?