vfprintf() has a 4096-byte memory leak?
Ryan T. Dean
rtdean at cytherianage.net
Sat Aug 2 05:21:51 PDT 2003
"Poul-Henning Kamp" wrote:
> In message <3F2B9C59.3060209 at cytherianage.net <http://lists.freebsd.org/mailman/listinfo/freebsd-current>>, "Ryan T. Dean" writes:
> >/Hey all-
/> >/ I was doing some app debugging tonight, and noticed what appears to
/> >/be a memory leak in vfprintf().
/>
> This is probably the buffer which stdio uses for all I/O.
>
> Try calling
> setbuf(stdout, NULL);
> setbuf(stderr, NULL);
>
> as the very first thing in your program, and you will probably see
> that it does not allocate the 4k buffer, you may also be able to
> measure the performance change due to this.
>
> In other words, what you see is perfectly normal, and to be expected,
> but if it is a problem for you, the above is the workaround.
Aha. setbuf(stdout, NULL); does prevent the buffer from being allocated.
However, in the case of stdout and stderr, if you don't setbuf() it to null,
a buffer is malloc'd. The corresponding free() is in fclose. So, if you
[f]printf() to stdout/stderr, and fclose(stdout/stderr), you are fine. If,
however, you don't know that buffers are being allocated for stdin/stdout
and don't fclose() or setbuf() to NULL, a 4096-byte chunk of memory is
allocated and never freed. For shits and giggles, I checked a DeadRat 8
box - no buffering by default. I guess the only reason I'm worried is the
potential number of programs in the ports tree originally written on a system
where stdout/stderr behave differently, or people (like myself) who didn't
have a clue any sort of output buffering was enabled on stdout/stderr, and as
a result have memory leaks. If the porter did their job, it shouldn't be an
issue (was caught, patched, and the patch submitted upstream), but, then, we
never know, right?
I don't know. I'm tired and not thinking the straightest. I'd like to
apologize for any incoherence in my thoughts. I appreciate the prompt reply.
-Ryan T. Dean
(Code tested below on FBSD)
test1.c:
#include <stdio.h>
int main (void)
{
printf("Test\n");
return 0;
}
test1 memory debug output:
1059825156: 1: *** alloc: at 'ra=0x2816ee86' for 4096 bytes, got '0x804b008|s1'
1059825156: 1: top 10 allocations:
1059825156: 1: total-size count in-use-size count source
1059825156: 1: 4096 1 4096 1 ra=0x2816ee86
1059825156: 1: 4096 1 4096 1 Total of 1
1059825156: 1: dumping not-freed pointers changed since 0:
1059825156: 1: not freed: '0x804b008|s1' (4096 bytes) from 'ra=0x2816ee86'
1059825156: 1: total-size count source
1059825156: 1: 4096 1 ra=0x2816ee86
1059825156: 1: 4096 1 Total of 1
1059825156: 1: unknown memory: 1 pointer, 4096 bytes
test2.c:
#include <stdio.h>
int main (void)
{
printf("Test\n");
fclose(stdout);
return 0;
}
test2 memory debug output:
1059825216: 1: *** alloc: at 'ra=0x2816ee86' for 4096 bytes, got '0x804b008|s1'
1059825216: 2: *** free: at 'ra=0x2815c431' pnt '0x804b008|s2': size 4096, alloced at 'ra=0x2816ee86'
1059825216: 2: top 10 allocations:
1059825216: 2: total-size count in-use-size count source
1059825216: 2: 4096 1 0 0 ra=0x2816ee86
1059825216: 2: 4096 1 0 0 Total of 1
1059825216: 2: dumping not-freed pointers changed since 0:
1059825216: 2: memory table is empty
test3.c:
#include <stdio.h>
int main (void)
{
setbuf(stdout, NULL);
printf("Test\n");
return 0;
}
test3 memory debug output:
(no output generated)
More information about the freebsd-current
mailing list