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