Memory leak in libCore.so

Dear Rooters
During investigation of memory leak in my standalone program I realized that there is something wrong with libCore.so library.
Here is very simple program:

#include <iostream>

using namespace std;

int main()
{
  cout<<"Hello"<<endl;
  return 0;
}

Lets compile it with root library, and run:

It looks like it runs fine… but it only looks like.
When I run it with valgrind (valgrind.org/) I’ve got:

Can someone investigate it, please?
I tried with different root versions (e.g 5.16/00)

Hi,

this is expected and nothing to worry. We are constantly trying to reduce the amount of “leakage” at the end of the process. It’s mostly because the TClass information needs to survive as long as possible, even while ROOT shuts down. Still, it’s not a problem, e.g. it does not increase with CPU time.

Axel.

Thank you for reply.

Can you explain why root cannot delete all object at the end of program? It is very non-standard behavior…
And why is it “nothing to worry”? Is this memory leak “under control” somehow? If yes then how to distinguish controled memory leak from uncontroled in debuger?

All my questions arise from my stand alone application where I have memory leak which crashes the program. If in root memory leaks are acceptable then how to debug it?

Hi,

as valgrind suggests, use -v to display info on the memory leaks. That will allow you to identify your memory leak.

Memory leaks are not relevant as long as they do not increase over runtime and eat up all memory: once the process ends the OS will free any memory allocated by the process.

Axel.

Is there any way that these leaks could be purged at some point (say I know when I’m exiting, and would like a clean bill of health to see if I have problems outside of root?). I think the biggest issue with this is that without the benefit of a good memory debugger (no valgrind on windows), it can be somewhat confusing from where leaks originate. Is there something like TROOT::Clean()?

Thanks

Hello… i hope its okay, to dig out an old thread like this, but i have more or less the same problem. I used this testprogram:

#include <iostream>
#include <TH1F.h>
#include <TH1F.h>
#include <TF1.h>
#include <TRandom3.h>
#include <TStyle.h>
#include <TCanvas.h>
#include <TLorentzVector.h>
#include <TROOT.h>
#include <TApplication.h>
#include <TStyle.h>
#include <TPad.h>
#include <TFile.h> 
#include <TH2F.h>
#include <TH1F.h>
#include <iostream>
#include <vector.h>
using namespace std;

int main()
{
  cout<<"Hello"<<endl;
  return 0;
} 

and used the root suppression file, that comes with root… nontheless i get many errors, shown in:
rafb.net/p/mAEs5D26.html

How can i supress those errors, and why are they a) there and b) not suppressed in the suppression file?

Thx for help :slight_smile:

Hi,

I get "The requested document was not found on this server. " for your file. Can you try again? Or b/g/zip and attach, please.

Axel.

I run with: valgrind --leak-check=yes --suppressions=/ashare/cernlib/Linux_fc3/root_pro/etc/valgrind-root.supp bin/testcase
And get the following error (which is not so extremly long, so i think i can post it here):

==21981== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 48 from 1)
==21981== malloc/free: in use at exit: 1,148,590 bytes in 25,963 blocks.
==21981== malloc/free: 53,242 allocs, 27,279 frees, 2,281,570 bytes allocated.
==21981== For counts of detected errors, rerun with: -v
==21981== searching for pointers to 25,963 not-freed blocks.
==21981== checked 5,989,836 bytes.
==21981==
==21981== 22 bytes in 1 blocks are possibly lost in loss record 8 of 70
==21981==    at 0x4005B65: operator new(unsigned) (vg_replace_malloc.c:163)
==21981==    by 0xBE128A: std::string::_Rep::_S_create(unsigned, unsigned, std::allocator<char> const&) (in /usr/lib/libstdc++.so.6.0.8)
==21981==    by 0xBE2084: (within /usr/lib/libstdc++.so.6.0.8)
==21981==    by 0xBE2296: std::string::string(char const*, std::allocator<char> const&) (in /usr/lib/libstdc++.so.6.0.8)
==21981==    by 0x41B1296: TClass::AddClass(TClass*) (in /share/cernlib/Linux_fc3/root_v5.18.00b1/lib/libCore.so)
==21981==    by 0x41B17E9: TClass::Init(char const*, short, std::type_info const*, TVirtualIsAProxy*, void (*)(void*, TMemberInspector&, char*), char const*, char const*, int, int) (in /share/cernlib/Linux_fc3/root_v5.18.00b1/lib/libCore.so)
==21981==    by 0x41B2594: TClass::TClass(char const*, short, std::type_info const&, TVirtualIsAProxy*, void (*)(void*, TMemberInspector&, char*), char const*, char const*, int, int) (in /share/cernlib/Linux_fc3/root_v5.18.00b1/lib/libCore.so)
==21981==    by 0x429A624: TQClass::TQClass(char const*, short, std::type_info const&, TVirtualIsAProxy*, void (*)(void*, TMemberInspector&, char*), char const*, char const*, int, int) (in /share/cernlib/Linux_fc3/root_v5.18.00b1/lib/libCore.so)
==21981==    by 0x429A57F: ROOT::TQObjectInitBehavior::CreateClass(char const*, short, std::type_info const&, TVirtualIsAProxy*, void (*)(void*, TMemberInspector&, char*), char const*, char const*, int, int) const (in /share/cernlib/Linux_fc3/root_v5.18.00b1/lib/libCore.so)
==21981==    by 0x41BE044: ROOT::TGenericClassInfo::GetClass() (in /share/cernlib/Linux_fc3/root_v5.18.00b1/lib/libCore.so)
==21981==    by 0x42A5F80: TQObject::Class() (in /share/cernlib/Linux_fc3/root_v5.18.00b1/lib/libCore.so)
==21981==    by 0x41468BD: TQObject::IsA() const (in /share/cernlib/Linux_fc3/root_v5.18.00b1/lib/libCore.so)
==21981==
==21981==
==21981== 62 (28 direct, 34 indirect) bytes in 1 blocks are definitely lost in loss record 19 of 70
==21981==    at 0x40053C0: malloc (vg_replace_malloc.c:149)
==21981==    by 0x4750F8A: G__memfunc_setup (in /share/cernlib/Linux_fc3/root_v5.18.00b1/lib/libCint.so)
==21981==    by 0x58389CE: G__cpp_setup_func2() (in /share/cernlib/Linux_fc3/root_v5.18.00b1/lib/libPhysics.so)
==21981==    by 0x5838FAA: G__cpp_setup_funcG__Physics (in /share/cernlib/Linux_fc3/root_v5.18.00b1/lib/libPhysics.so)
==21981==    by 0x58398A3: G__cpp_setupG__Physics (in /share/cernlib/Linux_fc3/root_v5.18.00b1/lib/libPhysics.so)
==21981==    by 0x4731936: G__call_setup_funcs (in /share/cernlib/Linux_fc3/root_v5.18.00b1/lib/libCint.so)
==21981==    by 0x5840216: G__cpp_setup_initG__Physics::G__cpp_setup_initG__Physics() (in /share/cernlib/Linux_fc3/root_v5.18.00b1/lib/libPhysics.so)
==21981==    by 0x5839A62: __static_initialization_and_destruction_0(int, int) (in /share/cernlib/Linux_fc3/root_v5.18.00b1/lib/libPhysics.so)
==21981==    by 0x5839AC4: _GLOBAL__I__ZN4ROOT20GenerateInitInstanceEPK15TFeldmanCousins (in /share/cernlib/Linux_fc3/root_v5.18.00b1/lib/libPhysics.so)
==21981==    by 0x5841268: (within /share/cernlib/Linux_fc3/root_v5.18.00b1/lib/libPhysics.so)
==21981==    by 0x57F53AC: (within /share/cernlib/Linux_fc3/root_v5.18.00b1/lib/libPhysics.so)
==21981==    by 0x73B1F2: call_init (in /lib/ld-2.5.so)
==21981==
==21981==
==21981== 200 bytes in 1 blocks are definitely lost in loss record 28 of 70
==21981==    at 0x40057F5: operator new[](unsigned) (vg_replace_malloc.c:195)
==21981==    by 0x41835EA: TArrayI::Set(int) (in /share/cernlib/Linux_fc3/root_v5.18.00b1/lib/libCore.so)
==21981==    by 0x411A8F5: TColor::SetPalette(int, int*) (in /share/cernlib/Linux_fc3/root_v5.18.00b1/lib/libCore.so)
==21981==    by 0x4159D1D: TStyle::SetPalette(int, int*) (in /share/cernlib/Linux_fc3/root_v5.18.00b1/lib/libCore.so)
==21981==    by 0x415A2A9: TStyle::Reset(char const*) (in /share/cernlib/Linux_fc3/root_v5.18.00b1/lib/libCore.so)
==21981==    by 0x415AF7C: TStyle::TStyle(char const*, char const*) (in /share/cernlib/Linux_fc3/root_v5.18.00b1/lib/libCore.so)
==21981==    by 0x415B783: TStyle::BuildStyles() (in /share/cernlib/Linux_fc3/root_v5.18.00b1/lib/libCore.so)
==21981==    by 0x414D471: TROOT::TROOT(char const*, char const*, void (**)()) (in /share/cernlib/Linux_fc3/root_v5.18.00b1/lib/libCore.so)
==21981==    by 0x414D955: ROOT::GetROOT() (in /share/cernlib/Linux_fc3/root_v5.18.00b1/lib/libCore.so)
==21981==    by 0x41707FC: TTimer::Reset() (in /share/cernlib/Linux_fc3/root_v5.18.00b1/lib/libCore.so)
==21981==    by 0x4170EDE: TTimer::TTimer(long, bool) (in /share/cernlib/Linux_fc3/root_v5.18.00b1/lib/libCore.so)
==21981==    by 0x417143D: _GLOBAL__I_gSingleShotCleaner (in /share/cernlib/Linux_fc3/root_v5.18.00b1/lib/libCore.so)
==21981==
==21981==
==21981== 204 bytes in 1 blocks are possibly lost in loss record 29 of 70
==21981==    at 0x4005B65: operator new(unsigned) (vg_replace_malloc.c:163)
==21981==    by 0x4151599: TStorage::ObjectAlloc(unsigned) (in /share/cernlib/Linux_fc3/root_v5.18.00b1/lib/libCore.so)
==21981==    by 0x42951C7: TObject::operator new(unsigned) (in /share/cernlib/Linux_fc3/root_v5.18.00b1/lib/libCore.so)
==21981==    by 0x429A551: ROOT::TQObjectInitBehavior::CreateClass(char const*, short, std::type_info const&, TVirtualIsAProxy*, void (*)(void*, TMemberInspector&, char*), char const*, char const*, int, int) const (in /share/cernlib/Linux_fc3/root_v5.18.00b1/lib/libCore.so)
==21981==    by 0x41BE044: ROOT::TGenericClassInfo::GetClass() (in /share/cernlib/Linux_fc3/root_v5.18.00b1/lib/libCore.so)
==21981==    by 0x42A5F80: TQObject::Class() (in /share/cernlib/Linux_fc3/root_v5.18.00b1/lib/libCore.so)
==21981==    by 0x41468BD: TQObject::IsA() const (in /share/cernlib/Linux_fc3/root_v5.18.00b1/lib/libCore.so)
==21981==    by 0x4142557: TQObject::GetListOfClassSignals() const (in /share/cernlib/Linux_fc3/root_v5.18.00b1/lib/libCore.so)
==21981==    by 0x4142BDB: TQObject::Emit(char const*) (in /share/cernlib/Linux_fc3/root_v5.18.00b1/lib/libCore.so)
==21981==    by 0x4143416: TQObject::~TQObject() (in /share/cernlib/Linux_fc3/root_v5.18.00b1/lib/libCore.so)
==21981==    by 0x4171294: __tcf_0 (in /share/cernlib/Linux_fc3/root_v5.18.00b1/lib/libCore.so)
==21981==    by 0x776C78: __cxa_finalize (in /lib/libc-2.5.so)
==21981==
==21981==
==21981== 121,076 bytes in 2,751 blocks are possibly lost in loss record 66 of 70
==21981==    at 0x40057F5: operator new[](unsigned) (vg_replace_malloc.c:195)
==21981==    by 0x4151E63: TStringRef::GetRep(int, int) (in /share/cernlib/Linux_fc3/root_v5.18.00b1/lib/libCore.so)
==21981==    by 0x415215B: TString::TString(char const*) (in /share/cernlib/Linux_fc3/root_v5.18.00b1/lib/libCore.so)
==21981==    by 0x418BAF7: TClassTable::Add(char const*, short, std::type_info const&, void (*)(), int) (in /share/cernlib/Linux_fc3/root_v5.18.00b1/lib/libCore.so)
==21981==    by 0x418BB80: ROOT::AddClass(char const*, short, std::type_info const&, void (*)(), int) (in /share/cernlib/Linux_fc3/root_v5.18.00b1/lib/libCore.so)
==21981==    by 0x41BE550: ROOT::TDefaultInitBehavior::Register(char const*, short, std::type_info const&, void (*)(), int) const (in /share/cernlib/Linux_fc3/root_v5.18.00b1/lib/libCore.so)
==21981==    by 0x41BD6E1: ROOT::TGenericClassInfo::Init(int) (in /share/cernlib/Linux_fc3/root_v5.18.00b1/lib/libCore.so)
==21981==    by 0x41BD7AB: ROOT::TGenericClassInfo::TGenericClassInfo(char const*, int, char const*, int, ROOT::TInitBehavior const*, void (*)(), int) (in /share/cernlib/Linux_fc3/root_v5.18.00b1/lib/libCore.so)
==21981==    by 0x4294E3C: ROOT::GenerateInitInstance() (in /share/cernlib/Linux_fc3/root_v5.18.00b1/lib/libCore.so)
==21981==    by 0x5A03B4A: __static_initialization_and_destruction_0(int, int) (in /share/cernlib/Linux_fc3/root_v5.18.00b1/lib/libTreePlayer.so)
==21981==    by 0x5A04568: _GLOBAL__I__ZN4ROOT20GenerateInitInstanceEPKNS_22TBranchProxyDescriptorE (in /share/cernlib/Linux_fc3/root_v5.18.00b1/lib/libTreePlayer.so)
==21981==    by 0x5A1744C: (within /share/cernlib/Linux_fc3/root_v5.18.00b1/lib/libTreePlayer.so)
==21981==
==21981== LEAK SUMMARY:
==21981==    definitely lost: 228 bytes in 2 blocks.
==21981==    indirectly lost: 34 bytes in 3 blocks.
==21981==      possibly lost: 121,302 bytes in 2,753 blocks.
==21981==    still reachable: 1,027,026 bytes in 23,205 blocks.
==21981==         suppressed: 0 bytes in 0 blocks.
==21981== Reachable blocks (those to which a pointer was found) are not shown.
==21981== To see them, rerun with: --show-reachable=yes

Hi,

Those seems to all be alright. There are not memory leak per se. Instead their are allocation that are kept for the duration of the process and could be deleted during the termination of the process but are not deleted in order to reduce the time it takes for the process to exit (i.e. deleting them would really server only one purpose: avoid valgrind from thinking it is a memory leak).

Cheers,
Philippe.