ruby extension memory leak tracking
Using a valgrind and a nice patch for ruby 1.8.6, I now have rb-brill-tagger leak free.
Here’s the process I went through. First off you need a linux environment to run valgrind. If you don’t already have one setup, I recommend fedora core. It’s super easy to run and has a pretty good track record with hardward. Also, yum is super easy to use to install new software.
First I svn co http://svn.ruby-lang.org/repos/ruby/branches/ruby_1_8_6
Then get the patch:
wget http://fauna.rubyforge.org/svn/bleak_house/trunk/ruby/valgrind.patch
Update patch now available here.
Apply the patch:
patch -p0 < valgrind.patch
Build ruby:
autoconf && ./configure --prefix=$HOME/work/ruby-valgrind && make && make install
Setup the new ruby environment:
export PATH=$HOME/work/ruby-valgrind/bin:$PATH
Verify you have the correct ruby:
which ruby
Install rubygems:
wget http://rubyforge.org/frs/download.php/35283/rubygems-1.1.1.tgztar -zxf rubygems-1.1.1.tgzcd rubygems-1.1.1ruby setup.rb install
Verify the rubygems install:
which gem
Install Rake:
gem install rake
Checking out rb-brill-tagger:
git clone git://github.com/taf2/rb-brill-tagger.gitcd rb-brill-taggerrake
Running valgrind:
valgrind --leak-check=full ruby test/tagger_test.rb
Valgrind will take much longer to run but once the process has finished you should get some output similar to this:
rb-brill-tagger> valgrind --leak-check=full ruby test/tagger_test.rb
==17160== Memcheck, a memory error detector.
==17160== Copyright (C) 2002-2007, and GNU GPL'd, by Julian Seward et al.
==17160== Using LibVEX rev 1804, a library for dynamic binary translation.
==17160== Copyright (C) 2004-2007, and GNU GPL'd, by OpenWorks LLP.
==17160== Using valgrind-3.3.0, a dynamic binary instrumentation framework.
==17160== Copyright (C) 2000-2007, and GNU GPL'd, by Julian Seward et al.
==17160== For more details, rerun with: -v
==17160==
loading tagger...
tagger loaded!
Loaded suite test/tagger_test
Started
time: 75.484142 sec 0.132478156802789 docs/sec
..
Finished in 76.943314 seconds.
2 tests, 1 assertions, 0 failures, 0 errors
==17160==
==17160== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 25 from 1)
==17160== malloc/free: in use at exit: 9,666,639 bytes in 176,968 blocks.
==17160== malloc/free: 1,897,877 allocs, 1,720,909 frees, 48,816,043 bytes allocated.
==17160== For counts of detected errors, rerun with: -v
==17160== searching for pointers to 176,968 not-freed blocks.
==17160== checked 7,364,900 bytes.
==17160==
==17160== 16 bytes in 1 blocks are definitely lost in loss record 1 of 17
==17160== at 0x4022828: malloc (vg_replace_malloc.c:207)
==17160== by 0x8070851: ruby_xmalloc (gc.c:114)
==17160== by 0x808C95B: local_append (parse.y:5640)
==17160== by 0x808CC8F: special_local_set (parse.y:6228)
==17160== by 0x80A4E58: rb_reg_search (re.c:946)
==17160== by 0x80B8B22: rb_str_split_m (string.c:3559)
==17160== by 0x8055885: call_cfunc (eval.c:5700)
==17160== by 0x805E0D1: rb_call0 (eval.c:5856)
==17160== by 0x805ECC0: rb_call (eval.c:6103)
==17160== by 0x805C733: rb_eval (eval.c:3479)
==17160== by 0x805C65E: rb_eval (eval.c:3473)
==17160== by 0x805AE4C: rb_eval (eval.c:3689)
==17160==
==17160==
==17160== 26 bytes in 9 blocks are definitely lost in loss record 2 of 17
==17160== at 0x4022828: malloc (vg_replace_malloc.c:207)
==17160== by 0x40FA1BF: strdup (in /lib/libc-2.6.so)
==17160== by 0x402BD41: tagger_context_add_to_lexicon (tagger.c:71)
==17160== by 0x402BBC8: BrillTagger_add_to_lexicon (rbtagger.c:26)
==17160== by 0x8055859: call_cfunc (eval.c:5709)
==17160== by 0x805E0D1: rb_call0 (eval.c:5856)
==17160== by 0x805ECC0: rb_call (eval.c:6103)
==17160== by 0x805C733: rb_eval (eval.c:3479)
==17160== by 0x805C8E6: rb_eval (eval.c:3133)
==17160== by 0x805E8BE: rb_call0 (eval.c:6007)
==17160== by 0x805ECC0: rb_call (eval.c:6103)
==17160== by 0x805C733: rb_eval (eval.c:3479)
==17160==
==17160==
==17160== 896 bytes in 30 blocks are possibly lost in loss record 13 of 17
==17160== at 0x4022828: malloc (vg_replace_malloc.c:207)
==17160== by 0x8070851: ruby_xmalloc (gc.c:114)
==17160== by 0x8054725: scope_dup (eval.c:8211)
==17160== by 0x805A07F: rb_yield_0 (eval.c:5078)
==17160== by 0x806353E: proc_invoke (eval.c:8622)
==17160== by 0x805E0D1: rb_call0 (eval.c:5856)
==17160== by 0x805ECC0: rb_call (eval.c:6103)
==17160== by 0x805C733: rb_eval (eval.c:3479)
==17160== by 0x8059E97: rb_yield_0 (eval.c:5027)
==17160== by 0x805A720: rb_yield (eval.c:5111)
==17160== by 0x80C6674: rb_ary_each (array.c:1138)
==17160== by 0x805E0D1: rb_call0 (eval.c:5856)
==17160==
==17160== LEAK SUMMARY:
==17160== definitely lost: 42 bytes in 10 blocks.
==17160== possibly lost: 896 bytes in 30 blocks.
==17160== still reachable: 9,665,701 bytes in 176,928 blocks.
==17160== suppressed: 0 bytes in 0 blocks.
==17160== Reachable blocks (those to which a pointer was found) are not shown.
==17160== To see them, rerun with: --leak-check=full --show-reachable=yes

Recent Comments