This is the mail archive of the glibc-bugs@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug libc/2226] New: Memory leak in fputws


When using fputws to write to a stream, 12K of memory is leaked for each stream.
I am using the delivered glibc-2.3.5-10 with g++ 4.0.0.

I am attaching 2 programs. The first just shows one call to fopen, fputws,
fflush and fclose. After the call to fopen, the process is consuming 180KB of
virtual memory, after the call to fputws this increases to 196KB and after the
close it drops to 188KB. The program can also be run to use fputs instead of
fputws and in this case, after the call to fopen, the process is consuming
180KB, after the call to fputs this is still 180KB and after the fclose, it
drops to 176KB.
The program can also be invoked so that the stream is set to non-buffering and
then fputws and fputs behave the same.

The second program basically does the same operation 10000 times and prints the
memory usage after the first open and after 10000 loops. For fputws, after the
first fopen, the consumption is 180KB and after 10000 loops it is 120,176KB (or
~12KB per loop). For fputs or non buffered fputws, the final consumption is
still only 176KB.

It looks like the buffer allocated by fputws is being partially leaked.

Program 1
---------
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <wchar.h>

int main(int argc, char ** argv)
{
        char buff[128];
        wchar_t w_err[10];
        char c_err[10];
        for (int i = 0; i <9;i++)
        {
                w_err[i]=L'A';
                c_err[i]='A';
        }

        if ( argc < 2 || ( argv[1][0] != 'C' && argv[1][0] != 'W' ) )
        {
                fprintf(stderr,"Usage: a.out C|W [N]\n");
                fprintf(stderr,"Pass an arg of W for fputws or C for fputs\n");
                fprintf(stderr,"Pass an optional N for a non-buffered stream\n");
                exit(1);
        }

        int no_buffer = 0;
        if ( argc == 3 )
        {
                if ( argv[2][0] == 'N' )
                        no_buffer = 1;
                else
                {
                        fprintf(stderr,"Usage: a.out C|W [N]\n");
                        fprintf(stderr,"Pass an arg of W for fputws or C for
fputs\n");
                        fprintf(stderr,"Pass an optional N for a non-buffered
stream\n");
                        exit(1);
                }
        }


        w_err[9]=0;
        c_err[9]=0;
        sprintf(buff,"grep VmData /proc/%d/status", getpid());
        fprintf(stderr,"Original Size\n");
        system ( buff );

        FILE * f = fopen("./x.txt", "a");
        fprintf(stderr,"After open\n");
        system ( buff );

        if ( no_buffer )
                setvbuf(f, NULL, _IONBF, 0 );

        if (argv[1][0] == 'C' )
        {
                fputs( c_err, f );
                fprintf(stderr,"After fputs\n");
                system ( buff );
        }
        else
        {
                fputws( w_err, f );
                fprintf(stderr,"After fputws\n");
                system ( buff );
        }

        fflush( f );

        fclose( f );
        fprintf(stderr,"After close\n");
        system ( buff );


        return 0;
}


Program 2
---------
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <wchar.h>

int main(int argc, char ** argv)
{
        char buff[128];
        wchar_t w_err[10];
        char c_err[10];
        for (int i = 0; i <9;i++)
        {
                w_err[i]=L'A';
                c_err[i]='A';
        }

        if ( argc < 2 || ( argv[1][0] != 'C' && argv[1][0] != 'W' ) )
        {
                fprintf(stderr,"Usage: a.out C|W [N]\n");
                fprintf(stderr,"Pass an arg of W for fputws or C for fputs\n");
                fprintf(stderr,"Pass an optional N for a non-buffered stream\n");
                exit(1);
        }

        int no_buffer = 0;
        if ( argc == 3 )
        {
                if ( argv[2][0] == 'N' )
                        no_buffer = 1;
                else
                {
                        fprintf(stderr,"Usage: a.out C|W [N]\n");
                        fprintf(stderr,"Pass an arg of W for fputws or C for
fputs\n");
                        fprintf(stderr,"Pass an optional N for a non-buffered
stream\n");
                        exit(1);
                }
        }


        w_err[9]=0;
        c_err[9]=0;
        sprintf(buff,"grep VmData /proc/%d/status", getpid());
        fprintf(stderr,"Original Size\n");
        system ( buff );

        int j;
        for ( j = 0;j < 10000; j++)
        {
                FILE * f = fopen("./x.txt", "a");
                if ( j == 0 )
                {
                        fprintf(stderr,"After first open\n");
                        system ( buff );
                }

                if ( no_buffer )
                        setvbuf(f, NULL, _IONBF, 0 );

                if (argv[1][0] == 'C' )
                        fputs( c_err, f );
                else
                        fputws( w_err, f );

                fflush( f );

                fclose( f );
        }

        fprintf(stderr,"After %d loops\n", j);
        system ( buff );


        return 0;
}

-- 
           Summary: Memory leak in fputws
           Product: glibc
           Version: 2.3.5
            Status: NEW
          Severity: critical
          Priority: P2
         Component: libc
        AssignedTo: drepper at redhat dot com
        ReportedBy: markxjohnson at earthlink dot net
                CC: glibc-bugs at sources dot redhat dot com
  GCC host triplet: Fedora Core 4/2.6.11-1.1369_FC4SMP


http://sourceware.org/bugzilla/show_bug.cgi?id=2226

------- You are receiving this mail because: -------
You are on the CC list for the bug, or are watching someone who is.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]