This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ 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]

Re: stl / pthreads leak, patch


Here is a sample program that will always leak memory. It has been
tested using both GCC-2.9.6 and GCC-3.1.1 on RedHat Linux versions 6.2,
7.2, and 7.3. It has been tested using single and multi-processor
machines:


////////////////////////////////////////////////////////////////////
// BEGIN:  stl_leaker.cpp                                         //
////////////////////////////////////////////////////////////////////
#define _GNU_SOURCE
#define _REENTRANT
#define _THREAD_SAFE
#include <pthread.h>
#include <iostream>
#include <string>
#include <unistd.h>
using namespace std;

void *processClient(void *clientArgs);
pthread_attr_t attrDetached;

int main(int argc, char **argv) 
{
	int numThreads = 20;
	pthread_attr_init(&attrDetached);
	pthread_attr_setdetachstate(&attrDetached, PTHREAD_CREATE_DETACHED);
	pthread_t clientThread;	//Threads are detached, don't care about
handle			
	for ( int threadCount = 0; threadCount <= numThreads; threadCount++ ) {
				
		if ( (pthread_create(&clientThread, &attrDetached, processClient,
(void *)NULL)) != 0 ) {
			cout << endl << "ERROR: Could not create client thread.";					
			break; 
		}							
	}
	sleep(10); //Make sure all detached threads have a chance to return	
	pthread_attr_destroy(&attrDetached);
	cout << endl << "DONE !" << endl;		
	return 0;
}

void *processClient(void *clientArgs) 
{	
	string s1, s2, s3, s4, s5, s6;
	s1.assign("blah123");
	s2.assign("blah123blah123");
	s3.assign("blah123blah123blah123");
	s4.assign("blah123blah123blah123blah123");
	s5.assign(s1 + s2);
	s6.assign(s3 + s2 + s1);	
	return NULL; 
}

////////////////////////////////////////////////////////////////////
// END: stl_leaker.cpp                                            //
////////////////////////////////////////////////////////////////////


This compile statement provides good debug output:

# g++ -g -DDEBUG stl_leaker.cpp -o stl_leaker -lpthread


Valgrind is an excellent, open-source tool for detecting memory leaks.
You can find it here  http://developer.kde.org/~sewardj/ .
Here is the command line for Valgrind that was used to detect the leak:

# valgrind --leak-check=yes --leak-resolution=high --num-callers=20
--show-reachable=yes --trace-children=yes -v ./stl_leaker


The following is sample Valgrind output using the compile line above. I
know for a fact these are not false positives. If configured to run a
long time, this program will keep snatching memory until there is none
left. Notice it always complains about line 490 in stl_alloc.h:
.
.
.
==4532== Reading suppressions file: /usr/local/lib/valgrind/default.supp
==4532== Reading syms from /home/sserv/stl_leaker
==4532== Reading syms from /lib/ld-2.2.4.so
==4532== Reading syms from /usr/local/lib/valgrind/valgrind.so
==4532== Reading syms from /usr/local/lib/valgrind/libpthread.so
==4532== Reading syms from /usr/lib/libstdc++-3-libc6.2-2-2.10.0.so
==4532== Reading syms from /lib/libm-2.2.4.so
==4532== Reading syms from /lib/libc-2.2.4.so
==4532== Estimated CPU clock rate is 300 MHz
==4532== 
valgrind's libpthread.so: IGNORED call to: pthread_attr_destroy
DONE !
valgrind's libpthread.so: libc_internal_tsd_get: dubious key 2
valgrind's libpthread.so: libc_internal_tsd_set: dubious key 2
valgrind's libpthread.so: libc_internal_tsd_get: dubious key 2
==4532== 
==4532== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 1 from 1)
--4532-- 
--4497-- supp:    1 __pthread_mutex_unlock/__register_frame_info
==4497== malloc/free: in use at exit: 4560 bytes in 2 blocks.
==4497== malloc/free: 23 allocs, 21 frees, 4812 bytes allocated.
==4497== 
==4497== searching for pointers to 2 not-freed blocks.
==4497== checked 4135240 bytes.
==4497== 
==4497== definitely lost: 0 bytes in 0 blocks.
==4497== possibly lost:   0 bytes in 0 blocks.
==4497== still reachable: 4560 bytes in 2 blocks.
==4497== 
==4497== 1280 bytes in 1 blocks are still reachable in loss record 1 of
2
==4497==    at 0x400457C4: malloc (vg_clientfuncs.c:100)
==4497==    by 0x804B147: ??? (/usr/include/g++-3/stl_alloc.h:490)
==4497==    by 0x804AF58: ??? (/usr/include/g++-3/stl_alloc.h:531)
==4497==    by 0x804AE82: ??? (/usr/include/g++-3/stl_alloc.h:419)
==4497==    by 0x804AD1C: ??? (/usr/include/g++-3/std/bastring.cc:33)
==4497==    by 0x804AAFE: ??? (/usr/include/g++-3/std/bastring.cc:60)
==4497==    by 0x804A93C: ??? (/usr/include/g++-3/std/bastring.cc:164)
==4497==    by 0x804A6CA: ??? (/usr/include/g++-3/std/bastring.h:223)
==4497==    by 0x804A558: ??? (/usr/include/g++-3/std/bastring.h:225)
==4497==    by 0x804A1B4: processClient(void *) (stl_leaker.cpp:37)
==4497==    by 0x40241166: thread_wrapper (vg_libpthread.c:521)
==4497==    by 0x4004A7FC: do__apply_in_new_thread_bogusRA
(vg_scheduler.c:2023)
==4497==    by 0x804A0DE: main (stl_leaker.cpp:28)
==4497==    by 0x402E5336: __libc_start_main
(../sysdeps/generic/libc-start.c:129)
==4497==    by 0x8049F61: pthread_mutex_unlock@@GLIBC_2.0 (in
/home/sserv/stl_leaker)
==4497== 
==4497== 3280 bytes in 1 blocks are still reachable in loss record 2 of
2
==4497==    at 0x400457C4: malloc (vg_clientfuncs.c:100)
==4497==    by 0x804B147: ??? (/usr/include/g++-3/stl_alloc.h:490)
==4497==    by 0x804AF58: ??? (/usr/include/g++-3/stl_alloc.h:531)
==4497==    by 0x804AE82: ??? (/usr/include/g++-3/stl_alloc.h:419)
==4497==    by 0x804AD1C: ??? (/usr/include/g++-3/std/bastring.cc:33)
==4497==    by 0x804AAFE: ??? (/usr/include/g++-3/std/bastring.cc:60)
==4497==    by 0x804A93C: ??? (/usr/include/g++-3/std/bastring.cc:164)
==4497==    by 0x804A7F5: ??? (/usr/include/g++-3/std/bastring.cc:131)
==4497==    by 0x804A730: ??? (/usr/include/g++-3/std/bastring.h:201)
==4497==    by 0x804A595: ??? (/usr/include/g++-3/std/bastring.h:480)
==4497==    by 0x804A25A: processClient(void *) (stl_leaker.cpp:42)
==4497==    by 0x40241166: thread_wrapper (vg_libpthread.c:521)
==4497==    by 0x4004A7FC: do__apply_in_new_thread_bogusRA
(vg_scheduler.c:2023)
==4497==    by 0x804A0DE: main (stl_leaker.cpp:28)
==4497==    by 0x402E5336: __libc_start_main
(../sysdeps/generic/libc-start.c:129)
==4497==    by 0x8049F61: pthread_mutex_unlock@@GLIBC_2.0 (in
/home/sserv/stl_leaker)
==4497== 
==4497== LEAK SUMMARY:
==4497==    definitely lost: 0 bytes in 0 blocks.
==4497==    possibly lost:   0 bytes in 0 blocks.
==4497==    still reachable: 4560 bytes in 2 blocks.
==4497== 
--4497--       lru: 0 epochs, 0 clearings.
--4497-- translate: new 1507 (23331 -> 307279), discard 0 (0 -> 0).
--4497--  dispatch: 0 basic blocks, 327/4209 sched events, 1539 tt_fast
misses.
--4497-- reg-alloc: 543 t-req-spill, 58421+3382 orig+spill uis, 7905
total-reg-r.
--4497--    sanity: 25 cheap, 1 expensive checks.


Thanks to anyone who helps this new programmer stay off the unemployment
line. :-( Any help greatly appreciated.

Ken




On Fri, 2002-08-09 at 15:29, Loren James Rittle wrote:
> Hi Ken, [You have been properly anonymized to allow a public response.
>          Please use the list.]
> 
> > I am experiencing the stl/pthreads memory leak problem when
> > compiling using g++[2.96]
> 
> I believe that this used the old libstdc++-v2 implementation.  Either
> way, the FSF didn't release gcc 2.96; you could contact Red Hat.
> 
> > and 3.1.1 on RedHat Linux 6.2. I read a posting from you that
> > mentioned you have a patch for this.
> 
> URL or other context?  Surely not written circa gcc 3.1.1 release time.
> 
> > Can you please let me know where I can find it? I seem to be having trouble.
> 
> > Any help much appreciated.
> 
> All patches related to known memory leaks in the libstdc++-v3 STL/threaded
> implementation are already in the GCC Repository.  I am fairly sure
> that no improvements/fixes in this area have been made post gcc 3.1.1
> release.
> 
> Please post the *smallest* reasonable test case with a leak if you
> want me to look at something in depth.  I do promise to look at such
> postings.
> 
> Regards,
> Loren



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