- Removed leakotron. It was not a very useful test, and hard to make

portable.
- Rewrote leak-tree to be deterministic and clearer.


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@9372
This commit is contained in:
Nicholas Nethercote 2009-03-12 03:00:05 +00:00
parent 0e1eb4b6c9
commit 190ad4143e
10 changed files with 74 additions and 339 deletions

View File

@ -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 \

View File

@ -1,46 +1,71 @@
#include <stdio.h>
#include <stdlib.h>
#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;
}

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -1,2 +1,2 @@
prog: leak-tree
vgopts: --leak-resolution=high
vgopts: -q --leak-check=full --leak-resolution=high

View File

@ -1,146 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#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;
}

View File

@ -1 +0,0 @@
PASS

View File

@ -1,2 +0,0 @@
prog: leakotron
stderr_filter: ../../tests/filter_sink