|
From: <sf...@ge...> - 2003-10-29 18:13:59
|
After reading the doc and writing a test program, it looks to me
like there can be a lot of memory leak bugs that won't be
caught. The basic problem is that a block will be considered
reachable even if it is only pointed to by memory which itself
is not reachable. For example, a circular-linked or doubly-linked
list that is leaked will not be detected. (I may try my hand at
fixing this by constructing non-circular graphs.)
My question has to do with pointers to blocks that are stored on the
stack. I thought that valgrind would NOT detect leaks if the ptrs
were stored on the stack, but it DOES detect them! The program
below makes sure that a pointer to the malloc done in z() is in
memory in unused stack space. But valgrind reports the block
as lost.
Does valgrind intentionally skip the stack when looking for lost
blocks?
-----
/* x.c */
#include <stdio.h>
struct x_s { struct x_s *xp; };
void z(char *cp)
{
char d1[64];
struct x_s *z;
char d2[64];
/* this code prevents optimizer from getting rid of d1 & d2 */
d1[0] = *cp; d2[0] = *cp;
printf("addr of stack-based arrays d1=%p, d2=%p\n", d1, d2);
z = (struct x_s *)malloc(sizeof(struct x_s));
z->xp = NULL;
/* this code prevents optimizer from keeping z in a register */
printf("addr of stack-based var z=%p, malloc=%p\n", &z, z);
/* look for malloc ptr in the stack dump at the end of main() */
}
void y(char *a, char *b)
{
char c[128]; /* allocate a bunch of stack so that z's pointer won't be
overwritten by subsequent calls */
/* code to prevent c from being optimized away */
c[0] = 0;
z(c);
*a = c[0]; *b = c[0];
}
int main(int argc, char **argv)
{
char d1[64];
struct x_s *x;
char d2[64];
struct x_s **p;
int i;
/* I think the following leak should not be detected by valgrind, but
somehow it does detect it. Why??? */
y(d1, d2);
/* leak (x loses scope when main returns) */
x = (struct x_s *)malloc(sizeof(struct x_s));
x->xp = NULL;
/* prevent optimizer from keeping x in a register */
printf("addr of stack var x=%p\n", &x);
/* print unused stack dump */
p = &x;
for (i = 0; i < 100; ++i) {
/* ignore the uninitialized accesses */
printf("stack[%p]=%p\n", p, *p);
--p;
}
} /* main */
|