Mpatrol detects memory leaks in tobject derived classes

Hi all!

I am using mpatrol to detect memory leaks in my library. I use these classes:
[ul]
[li] TVectorT[/li]
[li] TMap[/li]
[li] TObjArray[/li]
[li] TObjString[/li][/ul]
I delete all the instances and in the collection classes (TMap, TObjArray) I delete the members, too. Although mpatrol detects leaks in the lines where I instanciate these classes.

What am I doing wrong? Thanks for your answers. Johannes.

Could you post a running version of your test program?

Rene

Actually, I only deleted the members of TMap and not of TObjArray. That was one problem. I’ll have a one more look for the others.

Now I’m deleting my stuff like this:

[code]TObjArray rootVar = (TObjArray) tmpVar;
rootVar->Write(name, TObject::kSingleKey);

TIterator *iter = rootVar->MakeIterator();
TObject *cell;

while (cell = iter->Next()) {
delete cell;
}

delete iter;
delete rootVar;[/code]

Wouldn’t it be nice if the destructor of the collection classes deletes the members automatically? Just a question…

Johannes.

[quote=“joki”]
Wouldn’t it be nice if the destructor of the collection classes deletes the members automatically? Just a question…[/quote]
root.cern.ch/root/html/TCollecti … n:SetOwner

Ah cool, you made my day :smiley:

I knew, there’s something wrong with my code. Thx.

Hm, what’s wrong with this code?

[code]#define DEBUG

#include “TObjArray.h”
#include “TObjString.h”

#include “mex.h”

#include “mpatrol.h”

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
#if defined(DEBUG)
__mp_startleaktable();
#endif

TObjArray *array = new TObjArray();
TObjArray *cell = new TObjArray();

array->SetOwner();
cell->SetOwner();

TObjString *str1 = new TObjString("test1");
TObjString *str2 = new TObjString("test2");
TObjString *str3 = new TObjString("test3");

cell->Add(str2);
cell->Add(str3);

array->Add(str1);
array->Add(cell);

delete array;

#if defined(DEBUG)
__mp_stopleaktable();

__mp_leaktable(0, MP_LT_ALLOCATED, MP_LT_BOTTOM);
__mp_leaktable(0, MP_LT_FREED,     MP_LT_BOTTOM);
__mp_leaktable(0, MP_LT_UNFREED,   MP_LT_BOTTOM);
#endif

}
[/code]

mpatrol prints this leak table:

[code]bottom 5 allocated memory entries in leak table:

   bytes   count  location
--------  ------  --------
      20       1  test.cpp line 21
      20       1  test.cpp line 22
      20       1  test.cpp line 23
      40       1  test.cpp line 15
      40       1  test.cpp line 16
     140       5  total

bottom 1 freed memory entry in leak table:

   bytes   count  location
--------  ------  --------
      40       1  test.cpp line 15
      40       1  total

bottom 4 unfreed memory entries in leak table:

   bytes   count  location
--------  ------  --------
      20       1  test.cpp line 21
      20       1  test.cpp line 22
      20       1  test.cpp line 23
      40       1  test.cpp line 16
     100       4  total[/code]

Does this SetOwner trick work in nested collections?
Do I have to invoke the garbage collection by hand?

Does ROOT typically make garbage collection or just recursively call the destructors? Both methods seem to be implemented. What should I use?

[color=red]Edit:[/color]
I link only these libs: -lCore -lCint -lRIO -lXMLIO -lNet -lSQL -lRootAuth -lMathCore -lMatrix

Hi! Doesn’t anyone have an idea to this problem?

Should I write a bug report or is there a problem with my code?

I do not see any memory leak at all in the example that you posted. I ran the test
with the valgrind memory leak checker and with the ROOT stat tool.
To run with the ROOT memory monitoring tool (it monitors only the classes having a dictionary and this is the case for all the classes in your test.
To use this tool, modify $ROOTSYS/etc/system.rootrc and set (instead of 0)
Root.ObjectStat: 1
To test it run the script leak.C below (either interpreted with CINT or compiled with ACLIC

with CINT root -b -q leak.C with ACLIC root -b -q leak.C+
Which version of ROOT are you using?

Rene

[code]#include “TObjectTable.h”
#include “TObjArray.h”
#include "TObjString.h"
void leak() {
gObjectTable->Print();
TObjArray *array = new TObjArray();
TObjArray *cell = new TObjArray();

array->SetOwner();
cell->SetOwner();

TObjString *str1 = new TObjString(“test1”);
TObjString *str2 = new TObjString(“test2”);
TObjString *str3 = new TObjString(“test3”);

cell->Add(str2);
cell->Add(str3);

array->Add(str1);
array->Add(cell);
gObjectTable->Print();
delete array;
gObjectTable->Print();
}
[/code]

I use a self-compiled ROOT 5.19/04 on a 32 bit machine with OpenSuse Linux 10.3.

Running your test prints the following:

[code]Object statistics
class cnt on heap size total size heap size

TTimer 1 0 64 64 0
TList 130 130 44 5720 5720
TObjectTable 1 1 24 24 24
TROOT 1 0 296 296 0
TPluginManager 1 1 24 24 24
THashTable 3 3 40 120 120
TClassTable 1 1 12 12 12
TRandom3 1 1 2532 2532 2532
THashList 2 2 48 96 96
TObjString 329 329 20 6580 6580
TEnv 1 1 28 28 28
TEnvRec 121 121 44 5324 5324
TMap 1 0 28 28 0
TPair 329 329 20 6580 6580
TUnixSystem 1 1 268 268 268
TOrdCollection 5 5 44 220 220

Total: 928 925 3536 27916 27528

Object statistics
class cnt on heap size total size heap size

TTimer 1 0 64 64 0
TList 130 130 44 5720 5720
TObjectTable 1 1 24 24 24
TROOT 1 0 296 296 0
TPluginManager 1 1 24 24 24
THashTable 3 3 40 120 120
TClassTable 1 1 12 12 12
TRandom3 1 1 2532 2532 2532
THashList 2 2 48 96 96
TObjString 329 329 20 6580 6580
TEnv 1 1 28 28 28
TEnvRec 121 121 44 5324 5324
TMap 1 0 28 28 0
TPair 329 329 20 6580 6580
TUnixSystem 1 1 268 268 268
TOrdCollection 5 5 44 220 220

Total: 928 925 3536 27916 27528

Object statistics
class cnt on heap size total size heap size

TTimer 1 0 64 64 0
TList 130 130 44 5720 5720
TObjectTable 1 1 24 24 24
TROOT 1 0 296 296 0
TPluginManager 1 1 24 24 24
THashTable 3 3 40 120 120
TClassTable 1 1 12 12 12
TRandom3 1 1 2532 2532 2532
THashList 2 2 48 96 96
TObjString 329 329 20 6580 6580
TEnv 1 1 28 28 28
TEnvRec 121 121 44 5324 5324
TMap 1 0 28 28 0
TPair 329 329 20 6580 6580
TUnixSystem 1 1 268 268 268
TOrdCollection 5 5 44 220 220

Total: 928 925 3536 27916 27528

[/code]

The tables should differ from each other, shouldn’t they?

your output shows that you did not set
Root.ObjectStat: 1

Rene

Good point, sorry :blush:

What do these tables actually say? The heap size between start and end still differs.

Johannes.
output.txt (10.3 KB)