safe to fclose stdout to avoid memory leak?

Discussion in 'C Programming' started by Pietro Cerutti, Aug 20, 2007.

  1. Hi group,
    I just noticed that a malloc w/out relative free occurs in the standard
    C library (or at least, on my implementation of it).

    > cat test.c

    #include <stdio.h>
    int main(void) {
    printf("%s\n", "Hello");
    return (0);
    }

    > gcc -o test test.c
    > valgrind --leak-check=yes --show-reachable=yes -v ./test

    [snip bla bla]
    4096 bytes in 1 blocks are still reachable in loss record 1 of 1
    at 0x3C03B18F: malloc (in /usr/local/lib/valgrind/vgpreload_memcheck.so)
    by 0x3C116FD2: __smakebuf (in /lib/libc.so.6)
    by 0x3C116E77: __swsetup (in /lib/libc.so.6)
    by 0x3C10BF7F: __vfprintf (in /lib/libc.so.6)

    Now, if I modify the test program as follows:

    > cat test.c

    #include <stdio.h>
    int main(void) {
    printf("%s\n", "Hello");
    fclose(stdout);
    return (0);
    }

    and I recompile it:

    > gcc -o test test.c
    > valgrind --leak-check=yes --show-reachable=yes -v ./test

    ==1846== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
    ==1846== malloc/free: in use at exit: 0 bytes in 0 blocks.
    ==1846== malloc/free: 1 allocs, 1 frees, 4096 bytes allocated.

    My question are the following:
    - is it normal or is it likely to be a bug in my implementation of the C
    library?
    - is it safe to fclose stdout before returning to the OS?

    Thanks!

    --
    Pietro Cerutti

    PGP Public Key:
    http://gahr.ch/pgp
     
    Pietro Cerutti, Aug 20, 2007
    #1
    1. Advertising

  2. On Aug 20, 11:35 am, Pietro Cerutti <> wrote:
    > Hi group,
    > I just noticed that a malloc w/out relative free occurs in the standard
    > C library (or at least, on my implementation of it).
    >
    > > cat test.c

    >
    > #include <stdio.h>
    > int main(void) {
    > printf("%s\n", "Hello");
    > return (0);
    >
    > }
    > > gcc -o test test.c
    > > valgrind --leak-check=yes --show-reachable=yes -v ./test

    >
    > [snip bla bla]
    > 4096 bytes in 1 blocks are still reachable in loss record 1 of 1
    > at 0x3C03B18F: malloc (in /usr/local/lib/valgrind/vgpreload_memcheck.so)
    > by 0x3C116FD2: __smakebuf (in /lib/libc.so.6)
    > by 0x3C116E77: __swsetup (in /lib/libc.so.6)
    > by 0x3C10BF7F: __vfprintf (in /lib/libc.so.6)
    >
    > Now, if I modify the test program as follows:
    >
    > > cat test.c

    >
    > #include <stdio.h>
    > int main(void) {
    > printf("%s\n", "Hello");
    > fclose(stdout);
    > return (0);
    >
    > }
    >
    > and I recompile it:
    >
    > > gcc -o test test.c
    > > valgrind --leak-check=yes --show-reachable=yes -v ./test

    >
    > ==1846== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
    > ==1846== malloc/free: in use at exit: 0 bytes in 0 blocks.
    > ==1846== malloc/free: 1 allocs, 1 frees, 4096 bytes allocated.
    >
    > My question are the following:
    > - is it normal or is it likely to be a bug in my implementation of the C
    > library?
    > - is it safe to fclose stdout before returning to the OS?
    >
    > Thanks!
    >
    > --
    > Pietro Cerutti
    >
    > PGP Public Key:http://gahr.ch/pgp


    It is fine to close stdout. As to the valgrind's complaint, consider
    this code.

    #include <stdlib.h>
    static char *foo;
    int main(void)
    {
    foo=malloc(4);
    return 0;
    }

    The memory returned by malloc and pointed to by foo is still
    "reachable". It is not "leaked", there is a good pointer to it. If
    you inserted foo=NULL; after the malloc line, then it would be
    leaked. Apparently, the library is creating a buffer associated with
    stdout when stdout is first used and is keeping a pointer to that
    buffer until stdout is explicitly closed. Sounds harmless enough.
    Memory that is still "reachable" is not leaked per se, though it can
    still be a problem if, for example, you have a data structure like a
    hash table growing without bounds...

    -David
     
    David Resnick, Aug 20, 2007
    #2
    1. Advertising

  3. Pietro Cerutti

    Eric Sosman Guest

    Pietro Cerutti wrote On 08/20/07 11:35,:
    > Hi group,
    > I just noticed that a malloc w/out relative free occurs in the standard
    > C library (or at least, on my implementation of it).
    >
    >
    >>cat test.c

    >
    > #include <stdio.h>
    > int main(void) {
    > printf("%s\n", "Hello");
    > return (0);
    > }
    >
    >
    >>gcc -o test test.c
    >>valgrind --leak-check=yes --show-reachable=yes -v ./test

    >
    > [snip bla bla]
    > 4096 bytes in 1 blocks are still reachable in loss record 1 of 1
    > at 0x3C03B18F: malloc (in /usr/local/lib/valgrind/vgpreload_memcheck.so)
    > by 0x3C116FD2: __smakebuf (in /lib/libc.so.6)
    > by 0x3C116E77: __swsetup (in /lib/libc.so.6)
    > by 0x3C10BF7F: __vfprintf (in /lib/libc.so.6)
    >
    > Now, if I modify the test program as follows:
    >
    >
    >>cat test.c

    >
    > #include <stdio.h>
    > int main(void) {
    > printf("%s\n", "Hello");
    > fclose(stdout);
    > return (0);
    > }
    >
    > and I recompile it:
    >
    >
    >>gcc -o test test.c
    >>valgrind --leak-check=yes --show-reachable=yes -v ./test

    >
    > ==1846== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
    > ==1846== malloc/free: in use at exit: 0 bytes in 0 blocks.
    > ==1846== malloc/free: 1 allocs, 1 frees, 4096 bytes allocated.
    >
    > My question are the following:
    > - is it normal or is it likely to be a bug in my implementation of the C
    > library?


    It is unlikely to be a bug.

    > - is it safe to fclose stdout before returning to the OS?


    It is safe, but note that the program might not end
    when main() returns or when exit() is called. If any
    functions have been registered with atexit(), they will
    run after this point -- and if they try to use stdout ...

    --
     
    Eric Sosman, Aug 20, 2007
    #3
  4. Pietro Cerutti wrote:
    > Hi group,
    > I just noticed that a malloc w/out relative free occurs in the standard
    > C library (or at least, on my implementation of it).
    >
    >> cat test.c

    > #include <stdio.h>
    > int main(void) {
    > printf("%s\n", "Hello");
    > return (0);
    > }
    >
    >> gcc -o test test.c
    >> valgrind --leak-check=yes --show-reachable=yes -v ./test

    > [snip bla bla]
    > 4096 bytes in 1 blocks are still reachable in loss record 1 of 1
    > at 0x3C03B18F: malloc (in /usr/local/lib/valgrind/vgpreload_memcheck.so)
    > by 0x3C116FD2: __smakebuf (in /lib/libc.so.6)
    > by 0x3C116E77: __swsetup (in /lib/libc.so.6)
    > by 0x3C10BF7F: __vfprintf (in /lib/libc.so.6)
    >
    > Now, if I modify the test program as follows:
    >
    >> cat test.c

    > #include <stdio.h>
    > int main(void) {
    > printf("%s\n", "Hello");
    > fclose(stdout);
    > return (0);
    > }
    >
    > and I recompile it:
    >
    >> gcc -o test test.c
    >> valgrind --leak-check=yes --show-reachable=yes -v ./test

    > ==1846== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
    > ==1846== malloc/free: in use at exit: 0 bytes in 0 blocks.
    > ==1846== malloc/free: 1 allocs, 1 frees, 4096 bytes allocated.
    >
    > My question are the following:
    > - is it normal or is it likely to be a bug in my implementation of the C
    > library?
    > - is it safe to fclose stdout before returning to the OS?
    >
    > Thanks!
    >


    Thank you David and Eric for your points!

    --
    Pietro Cerutti

    PGP Public Key:
    http://gahr.ch/pgp
     
    Pietro Cerutti, Aug 20, 2007
    #4
  5. Pietro Cerutti

    Chris Torek Guest

    In article <2df02$46c9b4bf$50dabbcd$>
    Pietro Cerutti <> wrote:
    >Hi group,
    >I just noticed that a malloc w/out relative free occurs in the standard
    >C library (or at least, on my implementation of it).

    [snippage, some output from valgrind remaining:]
    >4096 bytes in 1 blocks are still reachable in loss record 1 of 1
    >at 0x3C03B18F: malloc (in /usr/local/lib/valgrind/vgpreload_memcheck.so)
    >by 0x3C116FD2: __smakebuf (in /lib/libc.so.6)
    >by 0x3C116E77: __swsetup (in /lib/libc.so.6)
    >by 0x3C10BF7F: __vfprintf (in /lib/libc.so.6)


    These function names suggest that your libc uses the stdio code I
    wrote for 4.xBSD (or something closely related / descended; I think
    my printf engine was originally named __svfprintf, for instance).

    Originally, I had -- or was going to have -- the code called at
    program exit iterate over all the open FILE data structures and
    "fclose" them. This would release the memory allocated by
    __smakebuf(), and also use the system's "close file" call on the
    associated file descriptor (normally fd 1). Someone pointed out,
    though, that it is "more efficient" on the BSD systems to just
    fflush() these files, to force pending output to appear, and then
    use the system's "exit" call to release all memory (including
    malloc()ed memory, without going through free() at all) and close
    all files (without using the system's "close file" call).

    If you or I were writing Standard C, this is not such a great idea.
    But I was not writing Standard C; I was implementing the C library
    in a system-specific manner. Because I was writing system-specific
    code, I could depend on behavior not prescribed by the C Standard,
    such as "memory gets freed automatically when the program terminates"
    and "files get closed automatically when the program terminates".
    In other words, as the implementor, I am *allowed* to cheat. :)

    (Note also that the function names I used are all in the implementor's
    namespace. I used names beginning with double underscores, which
    you -- as a "user" programmer -- must avoid. I, as an "implementor"
    programmer, must avoid any names that you can use. The double
    underscore prefix safely hides me from you, and you from me, except
    at the interfaces required by Standard C: fopen, fclose, and so
    on, in this case.)

    >My question are the following:
    >- is it normal or is it likely to be a bug in my implementation of the C
    >library?


    It is not really "normal" but it is not a "bug" either. Instead,
    it is a deliberate violation done in the name of efficiency,
    "knowing" various things (which I hope are still true today :) )
    about the system. (Anyone modifying the underlying system in a
    way that breaks these assumptions must also modify the C implementation.)

    >- is it safe to fclose stdout before returning to the OS?


    It should be safe, but unnecessary.
    --
    In-Real-Life: Chris Torek, Wind River Systems
    Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
    email: forget about it http://web.torek.net/torek/index.html
    Reading email is like searching for food in the garbage, thanks to spammers.
     
    Chris Torek, Aug 21, 2007
    #5
  6. In article <>,
    Chris Torek <> wrote:

    >But I was not writing Standard C; I was implementing the C library
    >in a system-specific manner. Because I was writing system-specific
    >code, I could depend on behavior not prescribed by the C Standard,
    >such as "memory gets freed automatically when the program terminates"
    >and "files get closed automatically when the program terminates".
    >In other words, as the implementor, I am *allowed* to cheat. :)


    If one were writing the code today (rather than in the 1980s) I think
    the advantage of having memory checkers show no leaks at exit would
    outweigh the (now insignificant) efficiency gain.

    -- Richard
    --
    "Consideration shall be given to the need for as many as 32 characters
    in some alphabets" - X3.4, 1963.
     
    Richard Tobin, Aug 21, 2007
    #6
  7. Chris Torek wrote:
    > In article <2df02$46c9b4bf$50dabbcd$>
    > Pietro Cerutti <> wrote:
    >> Hi group,
    >> I just noticed that a malloc w/out relative free occurs in the standard
    >> C library (or at least, on my implementation of it).

    > [snippage, some output from valgrind remaining:]
    >> 4096 bytes in 1 blocks are still reachable in loss record 1 of 1
    >> at 0x3C03B18F: malloc (in /usr/local/lib/valgrind/vgpreload_memcheck.so)
    >> by 0x3C116FD2: __smakebuf (in /lib/libc.so.6)
    >> by 0x3C116E77: __swsetup (in /lib/libc.so.6)
    >> by 0x3C10BF7F: __vfprintf (in /lib/libc.so.6)

    >
    > These function names suggest that your libc uses the stdio code I
    > wrote for 4.xBSD (or something closely related / descended; I think
    > my printf engine was originally named __svfprintf, for instance).
    >
    > Originally, I had -- or was going to have -- the code called at
    > program exit iterate over all the open FILE data structures and
    > "fclose" them. This would release the memory allocated by
    > __smakebuf(), and also use the system's "close file" call on the
    > associated file descriptor (normally fd 1). Someone pointed out,
    > though, that it is "more efficient" on the BSD systems to just
    > fflush() these files, to force pending output to appear, and then
    > use the system's "exit" call to release all memory (including
    > malloc()ed memory, without going through free() at all) and close
    > all files (without using the system's "close file" call).
    >
    > If you or I were writing Standard C, this is not such a great idea.
    > But I was not writing Standard C; I was implementing the C library
    > in a system-specific manner. Because I was writing system-specific
    > code, I could depend on behavior not prescribed by the C Standard,
    > such as "memory gets freed automatically when the program terminates"
    > and "files get closed automatically when the program terminates".
    > In other words, as the implementor, I am *allowed* to cheat. :)
    >
    > (Note also that the function names I used are all in the implementor's
    > namespace. I used names beginning with double underscores, which
    > you -- as a "user" programmer -- must avoid. I, as an "implementor"
    > programmer, must avoid any names that you can use. The double
    > underscore prefix safely hides me from you, and you from me, except
    > at the interfaces required by Standard C: fopen, fclose, and so
    > on, in this case.)
    >
    >> My question are the following:
    >> - is it normal or is it likely to be a bug in my implementation of the C
    >> library?

    >
    > It is not really "normal" but it is not a "bug" either. Instead,
    > it is a deliberate violation done in the name of efficiency,
    > "knowing" various things (which I hope are still true today :) )
    > about the system. (Anyone modifying the underlying system in a
    > way that breaks these assumptions must also modify the C implementation.)
    >
    >> - is it safe to fclose stdout before returning to the OS?

    >
    > It should be safe, but unnecessary.


    Hi Christ,
    thank you very much for your exhaustive explanation.
    So, in short terms, what you're saying is that valgrind notices that
    memory isn't deallocated at program exit (which is true) because it gets
    eventually free'd by the OS, so I don't have to worry about memory
    leaks, right?

    Regards,

    --
    Pietro Cerutti

    PGP Public Key:
    http://gahr.ch/pgp
     
    Pietro Cerutti, Aug 21, 2007
    #7
  8. On 21 Aug 2007 at 10:27, Pietro Cerutti wrote:
    > Chris Torek wrote:
    >> In article <2df02$46c9b4bf$50dabbcd$>
    >> Pietro Cerutti <> wrote:
    >>> Hi group,
    >>> I just noticed that a malloc w/out relative free occurs in the standard
    >>> C library (or at least, on my implementation of it).

    >> [snippage, some output from valgrind remaining:]
    >>> 4096 bytes in 1 blocks are still reachable in loss record 1 of 1
    >>> at 0x3C03B18F: malloc (in /usr/local/lib/valgrind/vgpreload_memcheck.so)
    >>> by 0x3C116FD2: __smakebuf (in /lib/libc.so.6)
    >>> by 0x3C116E77: __swsetup (in /lib/libc.so.6)
    >>> by 0x3C10BF7F: __vfprintf (in /lib/libc.so.6)

    >>
    >> These function names suggest that your libc uses the stdio code I
    >> wrote for 4.xBSD (or something closely related / descended; I think
    >> my printf engine was originally named __svfprintf, for instance).
    >>
    >> Originally, I had -- or was going to have -- the code called at
    >> program exit iterate over all the open FILE data structures and
    >> "fclose" them. This would release the memory allocated by
    >> __smakebuf(), and also use the system's "close file" call on the
    >> associated file descriptor (normally fd 1). Someone pointed out,
    >> though, that it is "more efficient" on the BSD systems to just
    >> fflush() these files, to force pending output to appear, and then
    >> use the system's "exit" call to release all memory (including
    >> malloc()ed memory, without going through free() at all) and close
    >> all files (without using the system's "close file" call).
    >>
    >> If you or I were writing Standard C, this is not such a great idea.
    >> But I was not writing Standard C; I was implementing the C library
    >> in a system-specific manner. Because I was writing system-specific
    >> code, I could depend on behavior not prescribed by the C Standard,
    >> such as "memory gets freed automatically when the program terminates"
    >> and "files get closed automatically when the program terminates".
    >> In other words, as the implementor, I am *allowed* to cheat. :)
    >>
    >> (Note also that the function names I used are all in the implementor's
    >> namespace. I used names beginning with double underscores, which
    >> you -- as a "user" programmer -- must avoid. I, as an "implementor"
    >> programmer, must avoid any names that you can use. The double
    >> underscore prefix safely hides me from you, and you from me, except
    >> at the interfaces required by Standard C: fopen, fclose, and so
    >> on, in this case.)
    >>
    >>> My question are the following:
    >>> - is it normal or is it likely to be a bug in my implementation of the C
    >>> library?

    >>
    >> It is not really "normal" but it is not a "bug" either. Instead,
    >> it is a deliberate violation done in the name of efficiency,
    >> "knowing" various things (which I hope are still true today :) )
    >> about the system. (Anyone modifying the underlying system in a
    >> way that breaks these assumptions must also modify the C implementation.)
    >>
    >>> - is it safe to fclose stdout before returning to the OS?

    >>
    >> It should be safe, but unnecessary.

    >
    > Hi Christ,
    > thank you very much for your exhaustive explanation.
    > So, in short terms, what you're saying is that valgrind notices that
    > memory isn't deallocated at program exit (which is true) because it gets
    > eventually free'd by the OS, so I don't have to worry about memory
    > leaks, right?


    I believe that is false on some versions of MS-DOS.

    >
    > Regards,
    >


    --
    Search the web: http://www.google.com
     
    Antoninus Twink, Aug 30, 2007
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Alexander Malkis
    Replies:
    8
    Views:
    536
    Alexander Malkis
    Apr 14, 2004
  2. Alex Vinokur

    freopen, fclose and stdout

    Alex Vinokur, Dec 3, 2003, in forum: C Programming
    Replies:
    4
    Views:
    8,429
    vidyaani
    Jan 11, 2013
  3. Roger23
    Replies:
    2
    Views:
    1,029
    Roger23
    Oct 12, 2006
  4. David Mathog

    fclose then fopen equivalent for stdout?

    David Mathog, Oct 25, 2006, in forum: C Programming
    Replies:
    20
    Views:
    2,100
    Jordan Abel
    Oct 27, 2006
  5. Sune
    Replies:
    14
    Views:
    890
    Chris Thomasson
    Aug 26, 2007
Loading...

Share This Page