diff --git a/memcheck/tests/Makefile.am b/memcheck/tests/Makefile.am index 90250a912..2d7934a3c 100644 --- a/memcheck/tests/Makefile.am +++ b/memcheck/tests/Makefile.am @@ -69,8 +69,6 @@ EXTRA_DIST = $(noinst_SCRIPTS) \ leak-pool-4.vgtest leak-pool-4.stderr.exp \ leak-pool-5.vgtest leak-pool-5.stderr.exp \ leak-tree.vgtest leak-tree.stderr.exp \ - leak-tree.stderr.exp2 leak-tree.stderr.exp64 \ - leakotron.vgtest leakotron.stdout.exp leakotron.stderr.exp \ linux-syslog-syscall linux-syslog-syscall.stderr.exp \ linux-syscalls-2007 linux-syscalls-2007.stderr.exp \ long_namespace_xml.vgtest long_namespace_xml.stdout.exp \ @@ -190,7 +188,7 @@ check_PROGRAMS = \ fprw fwrite inits inline \ leak-0 \ leak-cases \ - leak-cycle leak-pool leak-tree leakotron \ + leak-cycle leak-pool leak-tree \ linux-syslog-syscall \ linux-syscalls-2007 \ long_namespace_xml \ diff --git a/memcheck/tests/leak-tree.c b/memcheck/tests/leak-tree.c index 7570564a3..99575f987 100644 --- a/memcheck/tests/leak-tree.c +++ b/memcheck/tests/leak-tree.c @@ -1,46 +1,71 @@ #include #include +#include "leak.h" #include "../memcheck.h" -struct foo { - struct foo *l, *r; -}; +/* We build this tree: + + A + / \ + B C + / \ / \ + D E F G + + Then we leak D and C-F-G. +*/ -struct foo *mk(struct foo *l, struct foo *r) +typedef + struct _Node { + struct _Node *l; + struct _Node *r; + // Padding ensures the structu is the same size on 32-bit and 64-bit + // machines. + char padding[16 - 2*sizeof(struct _Node*)]; + } Node; + +Node* mk(void) { - struct foo *f = malloc(sizeof(*f)); - f->l = l; - f->r = r; - - return f; + Node *x = malloc(sizeof(Node)); + x->l = NULL; + x->r = NULL; + return x; } -int main() +// This is a definite root. +Node* t; + +void f(void) { - struct foo *volatile a, *volatile b, *volatile c; + // Building like this rather than "t = mk(mk(mk(NULL, NULL), ...)" seems to + // help avoid leaving pointers on the stack to supposedly-leaked blocks. + t = mk(); // A + t->l = mk(); // B + t->r = mk(); // C (48(16d,32i)/1 definitely leaked from here) + t->l->l = mk(); // D (16/1 definitely leaked from here) + t->l->r = mk(); // E + t->r->l = mk(); // F + t->r->r = mk(); // G - b = mk(mk(0, 0), 0); - - /* Partially leaked tree structure */ - a = mk(mk(mk(mk(mk(0, 0), 0), mk(mk(0, 0), b)), mk(0, 0)), mk(0,0)); - - a = NULL; - - VALGRIND_DO_LEAK_CHECK; - - b = NULL; /* now leak old b */ - - /* Completely leaked, but part of the structure is shared */ - b = mk(0,0); - b->l = b; - b->r = b; - - a = mk(b,b); - c = mk(b,b); - - a = b = c = 0; - - VALGRIND_DO_LEAK_CHECK; - - return 0; + // Sever B->D, leaking D + t->l->l = NULL; + + // Sever A->C, leaking C-F-G + t->r = NULL; } + +int main(void) +{ + DECLARE_LEAK_COUNTERS; + + GET_INITIAL_LEAK_COUNTS; + + // See leak-cases.c for why we do the work in f(). + f(); + + GET_FINAL_LEAK_COUNTS; + + PRINT_LEAK_COUNTS(stderr); + + return 0; +} + diff --git a/memcheck/tests/leak-tree.stderr.exp b/memcheck/tests/leak-tree.stderr.exp index 2c3c28b7a..25606a1be 100644 --- a/memcheck/tests/leak-tree.stderr.exp +++ b/memcheck/tests/leak-tree.stderr.exp @@ -1,52 +1,17 @@ +leaked: 64 bytes in 4 blocks +dubious: 0 bytes in 0 blocks +reachable: 48 bytes in 3 blocks +suppressed: 0 bytes in 0 blocks -searching for pointers to 11 not-freed blocks. -checked ... bytes. - -72 (8 direct, 64 indirect) bytes in 1 blocks are definitely lost in loss record ... of ... +16 bytes in 1 blocks are definitely lost in loss record ... of ... at 0x........: malloc (vg_replace_malloc.c:...) - by 0x........: mk (leak-tree.c:11) - by 0x........: main (leak-tree.c:25) - -LEAK SUMMARY: - definitely lost: 8 bytes in 1 blocks. - indirectly lost: 64 bytes in 8 blocks. - possibly lost: 0 bytes in 0 blocks. - still reachable: 16 bytes in 2 blocks. - suppressed: 0 bytes in 0 blocks. -Reachable blocks (those to which a pointer was found) are not shown. -To see them, rerun with: --leak-check=full --show-reachable=yes -searching for pointers to 14 not-freed blocks. -checked ... bytes. + by 0x........: mk (leak-tree.c:28) + by 0x........: f (leak-tree.c:44) + by 0x........: main (leak-tree.c:63) -8 bytes in 1 blocks are definitely lost in loss record ... of ... +48 (16 direct, 32 indirect) bytes in 1 blocks are definitely lost in loss record ... of ... at 0x........: malloc (vg_replace_malloc.c:...) - by 0x........: mk (leak-tree.c:11) - by 0x........: main (leak-tree.c:39) - - -88 (8 direct, 80 indirect) bytes in 1 blocks are definitely lost in loss record ... of ... - at 0x........: malloc (vg_replace_malloc.c:...) - by 0x........: mk (leak-tree.c:11) - by 0x........: main (leak-tree.c:25) - - -16 (8 direct, 8 indirect) bytes in 1 blocks are definitely lost in loss record ... of ... - at 0x........: malloc (vg_replace_malloc.c:...) - by 0x........: mk (leak-tree.c:11) - by 0x........: main (leak-tree.c:38) - -LEAK SUMMARY: - definitely lost: 24 bytes in 3 blocks. - indirectly lost: 88 bytes in 11 blocks. - possibly lost: 0 bytes in 0 blocks. - still reachable: 0 bytes in 0 blocks. - suppressed: 0 bytes in 0 blocks. -Reachable blocks (those to which a pointer was found) are not shown. -To see them, rerun with: --leak-check=full --show-reachable=yes - -ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) -malloc/free: in use at exit: 112 bytes in 14 blocks. -malloc/free: 14 allocs, 0 frees, 112 bytes allocated. -For a detailed leak analysis, rerun with: --leak-check=yes -For counts of detected errors, rerun with: -v + by 0x........: mk (leak-tree.c:28) + by 0x........: f (leak-tree.c:43) + by 0x........: main (leak-tree.c:63) diff --git a/memcheck/tests/leak-tree.stderr.exp2 b/memcheck/tests/leak-tree.stderr.exp2 deleted file mode 100644 index a1bdde41d..000000000 --- a/memcheck/tests/leak-tree.stderr.exp2 +++ /dev/null @@ -1,52 +0,0 @@ - -searching for pointers to 11 not-freed blocks. -checked ... bytes. - -8 bytes in 1 blocks are definitely lost in loss record ... of ... - at 0x........: malloc (vg_replace_malloc.c:...) - by 0x........: mk (leak-tree.c:11) - by 0x........: main (leak-tree.c:25) - -LEAK SUMMARY: - definitely lost: 8 bytes in 1 blocks. - indirectly lost: 0 bytes in 0 blocks. - possibly lost: 0 bytes in 0 blocks. - still reachable: 80 bytes in 10 blocks. - suppressed: 0 bytes in 0 blocks. -Reachable blocks (those to which a pointer was found) are not shown. -To see them, rerun with: --leak-check=full --show-reachable=yes -searching for pointers to 14 not-freed blocks. -checked ... bytes. - - -8 bytes in 1 blocks are definitely lost in loss record ... of ... - at 0x........: malloc (vg_replace_malloc.c:...) - by 0x........: mk (leak-tree.c:11) - by 0x........: main (leak-tree.c:39) - - -8 bytes in 1 blocks are definitely lost in loss record ... of ... - at 0x........: malloc (vg_replace_malloc.c:...) - by 0x........: mk (leak-tree.c:11) - by 0x........: main (leak-tree.c:38) - - -40 (8 direct, 32 indirect) bytes in 1 blocks are definitely lost in loss record ... of ... - at 0x........: malloc (vg_replace_malloc.c:...) - by 0x........: mk (leak-tree.c:11) - by 0x........: main (leak-tree.c:25) - -LEAK SUMMARY: - definitely lost: 24 bytes in 3 blocks. - indirectly lost: 32 bytes in 4 blocks. - possibly lost: 0 bytes in 0 blocks. - still reachable: 56 bytes in 7 blocks. - suppressed: 0 bytes in 0 blocks. -Reachable blocks (those to which a pointer was found) are not shown. -To see them, rerun with: --leak-check=full --show-reachable=yes - -ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) -malloc/free: in use at exit: 112 bytes in 14 blocks. -malloc/free: 14 allocs, 0 frees, 112 bytes allocated. -For a detailed leak analysis, rerun with: --leak-check=yes -For counts of detected errors, rerun with: -v diff --git a/memcheck/tests/leak-tree.stderr.exp64 b/memcheck/tests/leak-tree.stderr.exp64 deleted file mode 100644 index a0ba471ca..000000000 --- a/memcheck/tests/leak-tree.stderr.exp64 +++ /dev/null @@ -1,52 +0,0 @@ - -searching for pointers to 11 not-freed blocks. -checked ... bytes. - -80 (16 direct, 64 indirect) bytes in 1 blocks are definitely lost in loss record ... of ... - at 0x........: malloc (vg_replace_malloc.c:...) - by 0x........: mk (leak-tree.c:11) - by 0x........: main (leak-tree.c:25) - -LEAK SUMMARY: - definitely lost: 16 bytes in 1 blocks. - indirectly lost: 64 bytes in 4 blocks. - possibly lost: 0 bytes in 0 blocks. - still reachable: 96 bytes in 6 blocks. - suppressed: 0 bytes in 0 blocks. -Reachable blocks (those to which a pointer was found) are not shown. -To see them, rerun with: --leak-check=full --show-reachable=yes -searching for pointers to 14 not-freed blocks. -checked ... bytes. - - -16 bytes in 1 blocks are definitely lost in loss record ... of ... - at 0x........: malloc (vg_replace_malloc.c:...) - by 0x........: mk (leak-tree.c:11) - by 0x........: main (leak-tree.c:39) - - -16 bytes in 1 blocks are definitely lost in loss record ... of ... - at 0x........: malloc (vg_replace_malloc.c:...) - by 0x........: mk (leak-tree.c:11) - by 0x........: main (leak-tree.c:38) - - -80 (16 direct, 64 indirect) bytes in 1 blocks are definitely lost in loss record ... of ... - at 0x........: malloc (vg_replace_malloc.c:...) - by 0x........: mk (leak-tree.c:11) - by 0x........: main (leak-tree.c:25) - -LEAK SUMMARY: - definitely lost: 48 bytes in 3 blocks. - indirectly lost: 64 bytes in 4 blocks. - possibly lost: 0 bytes in 0 blocks. - still reachable: 112 bytes in 7 blocks. - suppressed: 0 bytes in 0 blocks. -Reachable blocks (those to which a pointer was found) are not shown. -To see them, rerun with: --leak-check=full --show-reachable=yes - -ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) -malloc/free: in use at exit: 224 bytes in 14 blocks. -malloc/free: 14 allocs, 0 frees, 224 bytes allocated. -For a detailed leak analysis, rerun with: --leak-check=yes -For counts of detected errors, rerun with: -v diff --git a/memcheck/tests/leak-tree.vgtest b/memcheck/tests/leak-tree.vgtest index 7a43b9446..2d4cb9a2f 100644 --- a/memcheck/tests/leak-tree.vgtest +++ b/memcheck/tests/leak-tree.vgtest @@ -1,2 +1,2 @@ prog: leak-tree -vgopts: --leak-resolution=high +vgopts: -q --leak-check=full --leak-resolution=high diff --git a/memcheck/tests/leakotron.c b/memcheck/tests/leakotron.c deleted file mode 100644 index 1b4b4f140..000000000 --- a/memcheck/tests/leakotron.c +++ /dev/null @@ -1,146 +0,0 @@ -#include -#include -#include -#include "../memcheck.h" -#include "leak.h" - -/* - Incompetent memory management - - Simulate what happens when trying to manage a dense brancy cyclic - structure with refcounting. - */ - -static long bytes, blocks; - -struct node { - struct node *l, *r; - int ref; -}; - -static void ref(struct node *n) -{ - if (n) - n->ref++; -} - -static void unref(struct node *n) -{ - if (n && --n->ref == 0) { - bytes -= sizeof(*n); - blocks--; - free(n); - } -} - -static struct node *alloc() -{ - struct node *n = malloc(sizeof(*n)); - n->l = n->r = NULL; - n->ref = 0; - - bytes += sizeof(*n); - blocks++; - - return n; -} - -static void assign(struct node **np, struct node *n) -{ - ref(n); - unref(*np); - - *np = n; -} - -static int rrange(int range) -{ - long long ret = rand() * (long long)range; - - return (int)(ret / RAND_MAX); -} - -#define ITER 100000 -#define N 1000 - -static struct node *nodes[N]; - -static struct node *mk() -{ - int idx = rrange(N); - struct node *n; - - /* - 50% recycle - 25% alloc new - 25% return NULL - */ - if (rand() > RAND_MAX/2) { - /* recycle existing block */ - n = nodes[idx]; - } else if (rand() > RAND_MAX/2) { - /* alloc new block */ - n = alloc(); - assign(&n->l, mk()); - assign(&n->r, mk()); - } else { - /* no block */ - n = NULL; - } - - assign(&nodes[idx], n); - - return n; -} - -int main() -{ - int i; - long total; - DECLARE_LEAK_COUNTERS; - - /* we require these longs to have same size as a machine word */ - assert(sizeof(long) == sizeof(void*)); - - /* get a baseline in case the runtime allocated some memory */ - GET_INITIAL_LEAK_COUNTS; - - for (i = 0; i < ITER; i++) { - mk(); - - if ((i % (ITER/10)) == 0) { - if (0) - printf("%ld living blocks, %ld bytes\n", - blocks, bytes); - //VALGRIND_DO_LEAK_CHECK; - } - } - - /* "free all memory" */ - for (i = 0; i < N; i++) - assign(&nodes[i], NULL); - - - if (0) - printf("FINISHED: %ld living blocks, %ld bytes\n", - blocks, bytes); - - GET_FINAL_LEAK_COUNTS; - - total = L_bytes + D_bytes + R_bytes + S_bytes; - - if (0) { - PRINT_LEAK_COUNTS(stderr); - } - - if (R_bytes != 0) - printf("FAILED: I freed everything, " - "but there's still %ld bytes (in %ld blocks) reachable\n", - R_bytes, R_blocks); - else if (total != bytes) - printf("FAILED: I count %ld bytes, leakcheck says %ld\n", - bytes, total); - else - printf("PASS\n"); - return 0; -} diff --git a/memcheck/tests/leakotron.stderr.exp b/memcheck/tests/leakotron.stderr.exp deleted file mode 100644 index e69de29bb..000000000 diff --git a/memcheck/tests/leakotron.stdout.exp b/memcheck/tests/leakotron.stdout.exp deleted file mode 100644 index 7ef22e9a4..000000000 --- a/memcheck/tests/leakotron.stdout.exp +++ /dev/null @@ -1 +0,0 @@ -PASS diff --git a/memcheck/tests/leakotron.vgtest b/memcheck/tests/leakotron.vgtest deleted file mode 100644 index 5609f19f0..000000000 --- a/memcheck/tests/leakotron.vgtest +++ /dev/null @@ -1,2 +0,0 @@ -prog: leakotron -stderr_filter: ../../tests/filter_sink