浜地です。

test/ruby 以下を valgrind かけてみたら
色々とあったようなので修正してみました。

* marshal.c

Marshal.dump('hoge')

でリークします。

* process.c

IO.popen(["echo bar"]) {}

でリークします。

* string.c

s = "foo" * 100
s2 = "foo" * 101
s.replace(s2)

でリークします。

* transcode.c

難解であまりよくわかってませんが、
test_transcode.rb がリークしてました。
上の while も何か間違ってると思うのですが。

あと test_regexp.rb も怒られてましたが、
難しそうなので諦めました。

Index: marshal.c
===================================================================
--- marshal.c	(revision 18324)
+++ marshal.c	(working copy)
@@ -803,6 +803,7 @@
     st_free_table(arg->symbols);
     st_free_table(arg->data);
     st_free_table(arg->compat_tbl);
+    if (arg->encodings) st_free_table(arg->encodings);
     DATA_PTR(arg->wrapper) = 0;
     arg->wrapper = 0;
     if (arg->taint) {
Index: process.c
===================================================================
--- process.c	(revision 18324)
+++ process.c	(working copy)
@@ -1953,6 +1953,8 @@
             goto fail;
     }
 
+    if (pairs)
+        xfree(pairs);
     return 0;
 
 fail:
Index: string.c
===================================================================
--- string.c	(revision 18324)
+++ string.c	(working copy)
@@ -453,6 +453,9 @@
 static VALUE
 str_replace_shared(VALUE str2, VALUE str)
 {
+    if (!STR_EMBED_P(str2) && !STR_SHARED_P(str2)) {
+	xfree(RSTRING(str2)->as.heap.ptr);
+    }
     if (RSTRING_LEN(str) <= RSTRING_EMBED_LEN_MAX) {
 	STR_SET_EMBED(str2);
 	memcpy(RSTRING_PTR(str2), RSTRING_PTR(str), RSTRING_LEN(str)+1);
Index: transcode.c
===================================================================
--- transcode.c	(revision 18324)
+++ transcode.c	(working copy)
@@ -110,6 +110,7 @@
     }
     if (!val) {
 	if (!st_lookup(transcoder_table, (st_data_t)key, &val)) {
+	    xfree(key);
 	    /* multistep logic, via UTF-8 */
 	    if (!encoding_equal(from_encoding, "UTF-8") &&
 		!encoding_equal(to_encoding, "UTF-8") &&
@@ -119,6 +120,7 @@
 	    return NULL;
 	}
     }
+    xfree(key);
     return (rb_transcoder *)val;
 }