Something I realised recently: in C, iterators are much better than
higher-order functions for traversing data structures. The higher-order
approach is too clumsy due to the lack of polymorphism and closures; you
have to use void* too much and it is more verbose than it should be.
Hence, I replaced all the uses of HT_first_match() and
HT_apply_to_all_nodes() with equivalent uses of the hashtable iterator.
Also replaced higher-order traversal functions for Memcheck's freed-list
and the thread stacks with iterators. That last change changes the
core/tool interface, so I've increased the version number.
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@4415 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/memcheck/mac_shared.c b/memcheck/mac_shared.c
index eb5f53f..ec48650 100644
--- a/memcheck/mac_shared.c
+++ b/memcheck/mac_shared.c
@@ -410,35 +410,20 @@
MemCheck for user blocks, which Addrcheck doesn't support. */
Bool (*MAC_(describe_addr_supp)) ( Addr a, AddrInfo* ai ) = NULL;
-/* Callback for searching thread stacks */
-static Bool addr_is_in_bounds(Addr stack_min, Addr stack_max, void *ap)
+/* Function used when searching MAC_Chunk lists */
+static Bool addr_is_in_MAC_Chunk(MAC_Chunk* mc, Addr a)
{
- Addr a = *(Addr *)ap;
-
- return (stack_min <= a && a <= stack_max);
-}
-
-/* Callback for searching free'd list */
-static Bool addr_is_in_MAC_Chunk(MAC_Chunk* mc, void *ap)
-{
- Addr a = *(Addr *)ap;
-
return VG_(addr_is_in_block)( a, mc->data, mc->size,
MAC_MALLOC_REDZONE_SZB );
}
-/* Callback for searching malloc'd lists */
-static Bool addr_is_in_HashNode(VgHashNode* sh_ch, void *ap)
-{
- return addr_is_in_MAC_Chunk( (MAC_Chunk*)sh_ch, ap );
-}
-
/* Describe an address as best you can, for error messages,
putting the result in ai. */
static void describe_addr ( Addr a, AddrInfo* ai )
{
MAC_Chunk* mc;
ThreadId tid;
+ Addr stack_min, stack_max;
/* Perhaps it's a user-def'd block ? (only check if requested, though) */
if (NULL != MAC_(describe_addr_supp)) {
@@ -446,29 +431,36 @@
return;
}
/* Perhaps it's on a thread's stack? */
- tid = VG_(first_matching_thread_stack)(addr_is_in_bounds, &a);
- if (tid != VG_INVALID_THREADID) {
- ai->akind = Stack;
- ai->stack_tid = tid;
- return;
+ VG_(thread_stack_reset_iter)();
+ while ( VG_(thread_stack_next)(&tid, &stack_min, &stack_max) ) {
+ if (stack_min <= a && a <= stack_max) {
+ ai->akind = Stack;
+ ai->stack_tid = tid;
+ return;
+ }
}
/* Search for a recently freed block which might bracket it. */
- mc = MAC_(first_matching_freed_MAC_Chunk)(addr_is_in_MAC_Chunk, &a);
- if (NULL != mc) {
- ai->akind = Freed;
- ai->blksize = mc->size;
- ai->rwoffset = (Int)a - (Int)mc->data;
- ai->lastchange = mc->where;
- return;
+ mc = MAC_(get_freed_list_head)();
+ while (mc) {
+ if (addr_is_in_MAC_Chunk(mc, a)) {
+ ai->akind = Freed;
+ ai->blksize = mc->size;
+ ai->rwoffset = (Int)a - (Int)mc->data;
+ ai->lastchange = mc->where;
+ return;
+ }
+ mc = mc->next;
}
/* Search for a currently malloc'd block which might bracket it. */
- mc = (MAC_Chunk*)VG_(HT_first_match)(MAC_(malloc_list), addr_is_in_HashNode, &a);
- if (NULL != mc) {
- ai->akind = Mallocd;
- ai->blksize = mc->size;
- ai->rwoffset = (Int)(a) - (Int)mc->data;
- ai->lastchange = mc->where;
- return;
+ VG_(HT_ResetIter)(MAC_(malloc_list));
+ while ( (mc = VG_(HT_Next)(MAC_(malloc_list))) ) {
+ if (addr_is_in_MAC_Chunk(mc, a)) {
+ ai->akind = Mallocd;
+ ai->blksize = mc->size;
+ ai->rwoffset = (Int)(a) - (Int)mc->data;
+ ai->lastchange = mc->where;
+ return;
+ }
}
/* Clueless ... */
ai->akind = Unknown;