Some memory leaks

Hi everybody,

I ran the BaBar analysis application in valgrind and searched for memory leaks which
seem to come from ROOT (and cint). This is what I found:

In thread/src/TPosixThread.cxx:

==9343== 36 bytes in 1 blocks are definitely lost in loss record 325 of 563
==9343== at 0x4002BD79: __builtin_new (vg_replace_malloc.c:172)
==9343== by 0x63D184D3: TPosixThread::Run(TThread *) (thread/src/TPosixThread.cxx:31)

Int_t TPosixThread::Run(TThread *th)
{
int det;
pthread_t id;
pthread_attr_t *attr = new pthread_attr_t;

pthread_attr_init(attr);

// Set detach state
det = (th->fDetached) ? PTHREAD_CREATE_DETACHED : PTHREAD_CREATE_JOINABLE;

pthread_attr_setdetachstate(attr, det);
int ierr = pthread_create(&id, attr, &TThread::Fun, th);
if (attr) pthread_attr_destroy(attr);

++++++++++++++
delete attr;

return ierr;
}


I don’t know how to fix this one in base/src/TStorage.cxx:

==9343== 408 bytes in 7 blocks are definitely lost in loss record 467 of 563
==9343== at 0x4002BD79: __builtin_new (vg_replace_malloc.c:172)
==9343== by 0x40AAD23E: TStorage::ObjectAlloc(unsigned int) (base/src/TStorage.cxx:344)

void *TStorage::ObjectAlloc(size_t sz)
{

space = (ULong_t) ::operator new(sz); <===========
AddToHeap(space, space+sz);
return (void*) space;
}


In netx/src/TXNetConn.cxx:

==9343== 48 bytes in 2 blocks are definitely lost in loss record 360 of 563
==9343== at 0x4002BD79: __builtin_new (vg_replace_malloc.c:172)
==9343== by 0x63C19B4D: TXPhyConnection::BuildXMessage(ESendRecvOptions, bool, bool) (in /afs/slac.stanford.edu/package/cernroot/vol21/cvs040908_1418/Linux24RH72_i386_gcc2953/lib/libNetx.so)
==9343== by 0x63C10789: TXConnectionMgr::ReadMsg(short, ESendRecvOptions) (in /afs/slac.stanford.edu/package/cernroot/vol21/cvs040908_1418/Linux24RH72_i386_gcc2953/lib/libNetx.so)
==9343== by 0x63C1360E: TXNetConn::ReadPartialAnswer(XReqErrorType &, unsigned int &, ClientRequest *, bool, void **, TXNetConn::EThreeStateReadHandler &) (in /afs/slac.stanford.edu/package/cernroot/vol21/cvs040908_1418/Linux24RH72_i386_gcc2953/lib/libNetx.so)
==9343== by 0x63C12737: TXNetConn::ClientServerCmd(ClientRequest *, void const *, void **, void *, bool) (in /afs/slac.stanford.edu/package/cernroot/vol21/cvs040908_1418/Linux24RH72_i386_gcc2953/lib/libNetx.so)
==9343== by 0x63C12868: TXNetConn::SendGenCommand(ClientRequest *, void const *, void **, void *, bool, char *, ServerResponseHeader *) (in /afs/slac.stanford.edu/package/cernroot/vol21/cvs040908_1418/Linux24RH72_i386_gcc2953/lib/libNetx.so)

The SafeDelete(cmdrespMex) in SendGenCommand does not always do its job, or it’s not always reached.


One big leak for which I don’t know how to attack it:

==9343== 363300 bytes in 3545 blocks are definitely lost in loss record 546 of 563
==9343== at 0x4002BE89: __builtin_vec_new (vg_replace_malloc.c:203)
==9343== by 0x4199357D: default_alloc(unsigned int) (…/…/…/libio/strstream.cc:36)
==9343== by 0x41A509F0: _IO_str_overflow (strops.c:148)
==9343== by 0x419939EC: strstreambuf::overflow(int) (in /afs/slac.stanford.edu/package/gcc/i386_linux2/gcc-2.95.2/lib/libstdc+±3-libc6.1-2-2.10.0.so)
==9343== by 0x41A4F68A: _IO_default_xsputn (genops.c:466)
==9343== by 0x4199264F: streambuf::xsputn(char const *, int) (in /afs/slac.stanford.edu/package/gcc/i386_linux2/gcc-2.95.2/lib/libstdc+±3-libc6.1-2-2.10.0.so)
==9343== by 0x4198FFC6: ostream::write(char const *, int) (in /afs/slac.stanford.edu/package/gcc/i386_linux2/gcc-2.95.2/lib/libstdc+±3-libc6.1-2-2.10.0.so)
==9343== by 0x419836C2: ostream & operator<<<char, string_char_traits, __default_alloc_template<true, 0> >(ostream &, basic_string<char, string_char_traits, __default_alloc_template<true, 0> > const&) (in /afs/slac.stanford.edu/package/gcc/i386_linux2/gcc-2.95.2/lib/libstdc+±3-libc6.1-2-2.10.0.so)
==9343== by 0x40B81101: TClassEdit::ResolveTypedef(char const *, bool) (metautils/src/TClassEdit.cxx:635
)
==9343== by 0x40AA3B11: TROOT::GetClass(char const *, bool) const (base/src/TROOT.cxx:851)

TClassEdit looks like:

        if (resolveAll || ShouldReplace(temp.c_str())) {
           answ << ResolveTypedef( temp.c_str(), resolveAll);
        } else {

==9244== 1578 bytes in 83 blocks are definitely lost in loss record 1259 of 1477
==9244== at 0x4002BE89: __builtin_vec_new (vg_replace_malloc.c:203)
==9244== by 0x40D305B4: TArrayC::Set(int) (cont/src/TArrayC.cxx:114)

if (n < 0) return;
if (n != fN) {
Char_t temp = fArray;
if (n != 0) {
fArray = new Char_t[n];
if (n < fN) memcpy(fArray,temp, n
sizeof(Char_t));
else {
memcpy(fArray,temp,fN*sizeof(Char_t));
memset(&fArray[fN],0,(n-fN)*sizeof(Char_t));
}
} else {
fArray = 0;
}
if (fN) delete [] temp;
fN = n;
}


The other “definitely lost” errors came from cint:
==9343== 2425 bytes in 2 blocks are definitely lost in loss record 491 of 563
==9343== at 0x4002BC8D: malloc (vg_replace_malloc.c:153)
==9343== by 0x411A78D1: G__store_dictposition (cint/src/scrupto.c:102)
==9343== by 0x41149EEE: G__loadfile_tmpfile (cint/src/loadfile.c:1213)

if(0==dictpos->ptype) {
int i;
dictpos->ptype = (char*)malloc(G__struct.alltag+1);
for(i=0;i<G__struct.alltag;i++) dictpos->ptype[i] = G__struct.type[i];
}

I dont’ know who is responsible for deleting dictpos->ptype. The same for the following:

==9343== 90 bytes in 20 blocks are definitely lost in loss record 418 of 563
==9343== at 0x4002BC8D: malloc (vg_replace_malloc.c:153)
==9343== by 0x4116533E: G__memfunc_para_setup (cint/src/newlink.c:8178)
==9343== by 0x4116500C: G__parse_parameter_link (cint/src/newlink.c:8126)

if(para_name[0]) {
G__p_ifunc->para_name[G__func_now][ifn]=(char*)malloc(strlen(para_name)+1);
strcpy(G__p_ifunc->para_name[G__func_now][ifn],para_name);
}

==9244== 123 bytes in 10 blocks are definitely lost in loss record 1000 of 1477
==9244== at 0x4002BC8D: malloc (vg_replace_malloc.c:153)
==9244== by 0x41384B5B: G__savestring (cint/src/ifunc.c:42)
==9244== by 0x413BD744: G__memfunc_setup (cint/src/newlink.c:7836)
==9244== by 0x41B143AC: G__cpp_setup_func3(void) (in /afs/slac.stanford.edu/package/cernroot/vol1/cvs040908_1418/Linux24RH72_i386_gcc2953-noOptimize-Debug/lib/libMatrix.so)

if(pbuf) free((void)(*pbuf));
pbuf = (char)malloc(strlen(name)+1);
return(strcpy(*pbuf,name));
}

Maybe this helps to reduce the leak rate in the upcoming ROOT versions.

Greetings,
Matthias