The glib library has a memory pool / slab allocator of its own. Mostly
when running glib programs under Valgrind, we bypass it completely by
setting GSLICE=always_malloc.

However, that's not optimal -- partly because it papers over the cases
where a program allocates using g_slice and then invalidly frees with
the normal (g_)free. So I wanted to add proper annotations to make it
work nicely with Valgrind. My attempt is below. The file being patched
is http://git.gnome.org/browse/glib/tree/glib/gslice.c


However, it doesn't quite work as I want -- the 'superblocks' used by
the slab allocator are allocated with memalign, so they are tracked by
valgrind already. And thus although I seem to mostly get the right
warnings at the right times, the allocation stack trace is the wrong
one. For example, this test case:

        foo = g_slice_alloc(20);
        foo[20] = 0;
        g_slice_free1(20, foo);
        foo = g_slice_alloc(20);
        g_free(foo);

...gives this output:

==18242== Invalid write of size 1
==18242==    at 0x4005CD: main (slice.c:9)
==18242==  Address 0x4f38014 is 20 bytes inside a block of size 496 alloc'd
==18242==    at 0x4A04360: memalign (vg_replace_malloc.c:532)
==18242==    by 0x4A043B9: posix_memalign (vg_replace_malloc.c:660)
==18242==    by 0x4C6831B: slab_allocator_alloc_chunk (gslice.c:1174)
==18242==    by 0x4C69A74: g_slice_alloc (gslice.c:682)
==18242==    by 0x4005B5: main (slice.c:7)
==18242== 
==18242== Invalid free() / delete / delete[]
==18242==    at 0x4A04D72: free (vg_replace_malloc.c:325)
==18242==    by 0x4005FF: main (slice.c:12)
==18242==  Address 0x4f38020 is 32 bytes inside a block of size 496 alloc'd
==18242==    at 0x4A04360: memalign (vg_replace_malloc.c:532)
==18242==    by 0x4A043B9: posix_memalign (vg_replace_malloc.c:660)
==18242==    by 0x4C6831B: slab_allocator_alloc_chunk (gslice.c:1174)
==18242==    by 0x4C69A74: g_slice_alloc (gslice.c:682)
==18242==    by 0x4005B5: main (slice.c:7)

How can I make Valgrind *forget* that the slab allocator's superblock
was originally allocated with memalign?

diff --git a/glib/gslice.c b/glib/gslice.c
index 05de6b3..19bdddc 100644
--- a/glib/gslice.c
+++ b/glib/gslice.c
@@ -52,6 +52,7 @@
 #include "gthread.h"
 #include "gthreadprivate.h"
 #include "glib_trace.h"
+#include "memcheck.h"
 
 /* the GSlice allocator is split up into 4 layers, roughly modelled after the 
slab
  * allocator and magazine extensions as outlined in:
@@ -304,6 +305,8 @@ g_slice_init_nomessage (void)
   mem_assert (sys_page_size == 0);
   mem_assert (MIN_MAGAZINE_SIZE >= 4);
 
+  VALGRIND_CREATE_MEMPOOL(allocator, 0, 0);
+
 #ifdef G_OS_WIN32
   {
     SYSTEM_INFO system_info;
@@ -831,11 +834,15 @@ g_slice_alloc (gsize mem_size)
             thread_memory_magazine1_reload (tmem, ix);
         }
       mem = thread_memory_magazine1_alloc (tmem, ix);
+      VALGRIND_MAKE_MEM_NOACCESS(mem, chunk_size);
+      VALGRIND_MEMPOOL_ALLOC(allocator, mem, mem_size);
     }
   else if (acat == 2)           /* allocate through slab allocator */
     {
       g_mutex_lock (allocator->slab_mutex);
       mem = slab_allocator_alloc_chunk (chunk_size);
+      VALGRIND_MAKE_MEM_NOACCESS(mem, chunk_size);
+      VALGRIND_MEMPOOL_ALLOC(allocator, mem, mem_size);
       g_mutex_unlock (allocator->slab_mutex);
     }
   else                          /* delegate to system malloc */
@@ -890,6 +897,8 @@ g_slice_free1 (gsize    mem_size,
         }
       if (G_UNLIKELY (g_mem_gc_friendly))
         memset (mem_block, 0, chunk_size);
+      VALGRIND_MEMPOOL_FREE(allocator, mem_block);
+      VALGRIND_MAKE_MEM_UNDEFINED(mem_block, sizeof(ChunkLink));
       thread_memory_magazine2_free (tmem, ix, mem_block);
     }
   else if (acat == 2)                   /* allocate through slab allocator */
@@ -897,6 +906,8 @@ g_slice_free1 (gsize    mem_size,
       if (G_UNLIKELY (g_mem_gc_friendly))
         memset (mem_block, 0, chunk_size);
       g_mutex_lock (allocator->slab_mutex);
+      VALGRIND_MEMPOOL_FREE(allocator, mem_block);
+      VALGRIND_MAKE_MEM_UNDEFINED(mem_block, sizeof(ChunkLink));
       slab_allocator_free_chunk (chunk_size, mem_block);
       g_mutex_unlock (allocator->slab_mutex);
     }
@@ -951,6 +962,8 @@ g_slice_free_chain_with_offset (gsize    mem_size,
             }
           if (G_UNLIKELY (g_mem_gc_friendly))
             memset (current, 0, chunk_size);
+          VALGRIND_MEMPOOL_FREE(allocator, current);
+          VALGRIND_MAKE_MEM_UNDEFINED(current, sizeof(ChunkLink));
           thread_memory_magazine2_free (tmem, ix, current);
         }
     }
@@ -966,6 +979,8 @@ g_slice_free_chain_with_offset (gsize    mem_size,
             abort();
           if (G_UNLIKELY (g_mem_gc_friendly))
             memset (current, 0, chunk_size);
+          VALGRIND_MEMPOOL_FREE(allocator, current);
+          VALGRIND_MAKE_MEM_UNDEFINED(current, sizeof(ChunkLink));
           slab_allocator_free_chunk (chunk_size, current);
         }
       g_mutex_unlock (allocator->slab_mutex);


-- 
dwmw2



------------------------------------------------------------------------------
Beautiful is writing same markup. Internet Explorer 9 supports
standards for HTML5, CSS3, SVG 1.1,  ECMAScript5, and DOM L2 & L3.
Spend less time writing and  rewriting code and more time creating great
experiences on the web. Be a part of the beta today.
http://p.sf.net/sfu/beautyoftheweb
_______________________________________________
Valgrind-users mailing list
Valgrind-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/valgrind-users

Reply via email to