Memory corruption when calling TTree::Draw (const char *varexp, const TCut &selection)

Hello Rooters,

ROOT 5.34/36 (v5-34-36@v5-34-36, Apr 05 2016, 10:25:45 on linuxx8664gcc)
CINT/ROOT C/C++ Interpreter version 5.18.00, July 2, 2010

My problem which I call “memory corruption” has been expressing itself in different ways (and sometimes not at all) based on what compiler I use to compile the code (on different machines), the order of my code, etc. The common theme of it coming up seems to be my call to TTree::Draw (const char *varexp, const TCut &selection). Both times I tried to invoke this call in my code lead to seemingly random takeovers of memory: overwriting the TCut selection argument passed in, overwriting a TGraph and TVectorT instances that are protected members of my C++ class called Cell. This happens with or without the TCut argument (if and when it happens).

The entire project is quite large, and of course this isn’t what I would call a “reproducible” problem, but I’ve provided where the call occurs for context and tried to remove the irrelevant parts for readability.

Header file of Cell, the class containing TVectorDs being overwritten, and the derived classes QCell and T0Cell:

class Cell{

protected:
  TVectorD xlo,xmid,xhi,ylo,ymid,yhi; //the x and y coordinates defining each cell
  int n_cell; //number of cells
  TFile* f;
public:
  //functions
  Cell(double delX, double delY, double rad, double X0=0, double Y0=0); //Problem persists with this constructor (no TFiles involved).
  Cell(const char* filename); //load from filename
  virtual ~Cell();
  void ResizeVectors(int n);
   .....
   ..
   .
   
};

class Q_Cell: public Cell{
private:
  TVectorD Q_mean,Q_err; //Q_std; //mean, mean error, and standard deviation
  //TH2D *hist_Q;
  //TGraph2DErrors *Q_graph2D; //graph of the Qmean in each cell;
public:
  Q_Cell(double delX, double delY, double rad, double X0=0, double Y0=0);
  Q_Cell(const char* filename); //load from filename
  ~Q_Cell();
......
};

class T0_Cell: public Cell{
private:
  TVectorD T0_abs, T0_abs_err, T0_rel; //absolute and relative T0 of cell; relative to rel_idx cell (0 by default)
  int rel_idx;
public:
  T0_Cell(double delX, double delY, double rad, double X0=0, double Y0=0);
  T0_Cell(const char* filename); //load from filename
  ~T0_Cell();
  void ResizeVectors(int n); //resize local vectors
....
  
};

The function where the class instances are initialized and mysteriously “dismembered” when TTree::Draw is invoked.

int Calibration::GenerateT0CorrectionMap(int QCalID, int T0CalID){
//Declare instances of my derived classes of Cell
 T0_Cell tcell();
 Q_Cell qcell();//Initialize Q cell instance 

//Check values of TVectorDs via TVectorD::Print(), looks good here 
 qcell.PrintClass();
 tcell.PrintClass();

//Declare some variables
 int n = qcell.GetNCells();
 double Qmean,T0mean,T0err;
 Qmean=T0mean=T0err=0;
 TCut xyCellCut,QCellCut;
 TH1D* h_tcell = NULL;
 TF1* t0Fit = NULL;

 //start a loop
 for(int i=0;i<n;i++){
 //Construct my TCuts based on class content
  xyCellCut = qcell.GetXYCut(i,"MCPHitPosAA.X", "MCPHitPosAA.Y");
  Qmean = qcell.GetQMean(i);
  ostringstream stm;
  stm << Qmean;
  string dumstr = "QMCP>"+ stm.str();
  QCellCut=dumstr.c_str();
  cout<<QCellCut<<endl; 
  //Invoke TTree::Draw function of OutTrees[0][0] in order to create a new hist and fill it with TOFAA according to TCut selection. Check return value -- looks good. 
  cout<<CurrentAnalyzer->OutTrees[0][0]->Draw("TOFAA>>h_tcell_internal(100,-20,20)", xyCellCut+QCellCut)<<endl; //h_tcell_internal belongs to OutTrees[0][0] and will be destroyed upon closing
  //Assign h_tcell  pointer to newly created hist by TTree::Draw and do stuff with it
  h_tcell = (TH1D*) gDirectory->Get("h_tcell_internal");//brings into memory, still belongs to OutTrees directory
  //h_tcell->Fit("gaus","Quiet");
  //t0Fit = (TF1*) h_tcell->GetFunction("gaus");
  //T0mean = t0Fit->GetParameter(1);
  //T0err = t0Fit->GetParError(1);
  //tcell.SetPoint(i,T0mean,T0err);
 } 
 //Recheck contents TVectorD members of base class Cell via Print() and get garbage for one of them which never stops printing
  qcell.PrintClass();
  tcell.PrintClass();
}

The output stream is below. You can see printing the first few vectors of each class indicates correct assignment. When I reprint after the loop, one of the vectors now spans over unallocated memory and actually runs into the other vectors in the class (you can tell by scrolling down until the numbers are a series of similarly valued ints again).

[code]Vector (37) is as follows

 |        1  |

0 |-10
1 |0
2 |10
3 |-20
4 |-10
5 |0
6 |10
7 |20
8 |-30
9 |-20
10 |-10
11 |0
12 |10
13 |20
14 |30
15 |-30
16 |-20
17 |-10
18 |0
19 |10
20 |20
21 |30
22 |-30
23 |-20
24 |-10
25 |0
26 |10
27 |20
28 |30
29 |-20
30 |-10
31 |0
32 |10
33 |20
34 |-10
35 |0
36 |10

Vector (37) is as follows

 |        1  |

0 |0
1 |0
2 |0
3 |0
4 |0
5 |0
6 |0
7 |0
8 |0
9 |0
10 |0
11 |0
12 |0
13 |0
14 |0
15 |0
16 |0
17 |0
18 |0
19 |0
20 |0
21 |0
22 |0
23 |0
24 |0
25 |0
26 |0
27 |0
28 |0
29 |0
30 |0
31 |0
32 |0
33 |0
34 |0
35 |0
36 |0

Vector (37) is as follows

 |        1  |

0 |-10
1 |0
2 |10
3 |-20
4 |-10
5 |0
6 |10
7 |20
8 |-30
9 |-20
10 |-10
11 |0
12 |10
13 |20
14 |30
15 |-30
16 |-20
17 |-10
18 |0
19 |10
20 |20
21 |30
22 |-30
23 |-20
24 |-10
25 |0
26 |10
27 |20
28 |30
29 |-20
30 |-10
31 |0
32 |10
33 |20
34 |-10
35 |0
36 |10

QMCP>38497.3
1757
QMCP>36327.1
1945
QMCP>32089.9
1680
QMCP>41544.9
2162
QMCP>38230.4
2557
QMCP>33750
2828
QMCP>30291.1
2698
QMCP>28228.5
2354
QMCP>41963.9
1723
QMCP>41056
2496
QMCP>33293.9
2903
QMCP>27585.7
3125
QMCP>24273.6
2997
QMCP>21856
2687
QMCP>18495.1
1813
QMCP>39108.1
1956
QMCP>35828.4
2771
QMCP>27541.6
3163
QMCP>21102.2
3430
QMCP>18398.2
3057
QMCP>16600.3
2830
QMCP>14368.5
2114
QMCP>29582.1
1734
QMCP>27290.4
2606
QMCP>21482.3
2943
QMCP>17786.3
3080
QMCP>14493.9
2794
QMCP>13401.8
2576
QMCP>12301.5
1770
QMCP>18463.6
2192
QMCP>15008.8
2518
QMCP>14421.4
2678
QMCP>12978.2
2520
QMCP>12333.7
2206
QMCP>16946.6
1654
QMCP>16686.5
1850
QMCP>12999.2
1689

Vector (37) is as follows

 |        1  |

0 |-10
1 |0
2 |10
3 |-20
4 |-10
5 |0
6 |10
7 |20
8 |-30
9 |-20
10 |-10
11 |0
12 |10
13 |20
14 |30
15 |-30
16 |-20
17 |-10
18 |0
19 |10
20 |20
21 |30
22 |-30
23 |-20
24 |-10
25 |0
26 |10
27 |20
28 |30
29 |-20
30 |-10
31 |0
32 |10
33 |20
34 |-10
35 |0
36 |10

Vector (37) is as follows

 |        1  |

0 |0
1 |0
2 |0
3 |0
4 |0
5 |0
6 |0
7 |0
8 |0
9 |0
10 |0
11 |0
12 |0
13 |0
14 |0
15 |0
16 |0
17 |0
18 |0
19 |0
20 |0
21 |0
22 |0
23 |0
24 |0
25 |0
26 |0
27 |0
28 |0
29 |0
30 |0
31 |0
32 |0
33 |0
34 |0
35 |0
36 |0

Vector (747690044) is as follows

 |        1  |

1076613053 |-10
1076613054 |0
1076613055 |10
1076613056 |-20
1076613057 |-10
1076613058 |0
1076613059 |10
1076613060 |20
1076613061 |-30
1076613062 |-20
1076613063 |-10
1076613064 |0
1076613065 |10
1076613066 |20
1076613067 |30
1076613068 |-30
1076613069 |-20
1076613070 |-10
1076613071 |0
1076613072 |10
1076613073 |20
1076613074 |30
1076613075 |-30
1076613076 |-20
1076613077 |-10
1076613078 |0
1076613079 |10
1076613080 |20
1076613081 |30
1076613082 |-20
1076613083 |-10
1076613084 |0
1076613085 |10
1076613086 |20
1076613087 |-10
1076613088 |0
1076613089 |10
1076613090 |2.42092e-322
1076613091 |6.89873e-310
1076613092 |3.13151e-294
1076613093 |1.73416e-316
1076613094 |1.73416e-316
1076613095 |1.1755e+214
1076613096 |2.42092e-322
1076613097 |6.89873e-310
1076613098 |1.71224e-316
1076613099 |1.40825e-316
1076613100 |1.72675e-316
1076613101 |2.37152e-322
1076613102 |4.00193e-322
1076613103 |9.48702e+170
1076613104 |1.04636e+242
1076613105 |2.05095e-80
1076613106 |4.09697e-80
1076613107 |1.1755e+214
1076613108 |4.82582e+276
1076613109 |3.3127e+150
1076613110 |1.99035e+161
1076613111 |1.42559e-312
1076613112 |4.79244e-322
1076613113 |2.86881e-317
1076613114 |3.13151e-294
1076613115 |1.82804e-322
1076613116 |1.71335e-316
1076613117 |0
1076613118 |0
1076613119 |0
1076613120 |0
1076613121 |0
1076613122 |-2.35344e-185
1076613123 |4.74303e-322
1076613124 |4.79244e-322
1076613125 |2.86881e-317
1076613126 |3.13151e-294
1076613127 |1.82804e-322
1076613128 |1.72677e-316
1076613129 |0
1076613130 |0
1076613131 |0
1076613132 |0
1076613133 |0
1076613134 |-2.35344e-185
1076613135 |6.89873e-310
1076613136 |1.5069e-321
1076613137 |-15
1076613138 |-5
1076613139 |5
1076613140 |-25
1076613141 |-15
1076613142 |-5
1076613143 |5
1076613144 |15
1076613145 |-35
1076613146 |-25
1076613147 |-15
1076613148 |-5
1076613149 |5
1076613150 |15
1076613151 |25
1076613152 |-35
1076613153 |-25
1076613154 |-15
1076613155 |-5
1076613156 |5
1076613157 |15
1076613158 |25
1076613159 |-35
1076613160 |-25
1076613161 |-15
1076613162 |-5
1076613163 |5
1076613164 |15
1076613165 |25
1076613166 |-25
1076613167 |-15
1076613168 |-5
1076613169 |5
1076613170 |15
1076613171 |-15
1076613172 |-5
1076613173 |5
1076613174 |1.5069e-321
1076613175 |-5
1076613176 |5
1076613177 |15
1076613178 |-15
1076613179 |-5
1076613180 |5
1076613181 |15
1076613182 |25
1076613183 |-25
1076613184 |-15
1076613185 |-5
1076613186 |5
1076613187 |15
1076613188 |25
1076613189 |35
1076613190 |-25
1076613191 |-15
1076613192 |-5
1076613193 |5
1076613194 |15
1076613195 |25
1076613196 |35
1076613197 |-25
1076613198 |-15
1076613199 |-5
1076613200 |5
1076613201 |15
1076613202 |25
1076613203 |35
1076613204 |-15
1076613205 |-5
1076613206 |5
1076613207 |15
1076613208 |25
1076613209 |-5
1076613210 |5
1076613211 |15
1076613212 |1.5069e-321
1076613213 |-35
1076613214 |-35
1076613215 |-35
1076613216 |-25
1076613217 |-25
1076613218 |-25
1076613219 |-25
1076613220 |-25
1076613221 |-15
1076613222 |-15
1076613223 |-15
1076613224 |-15
1076613225 |-15
1076613226 |-15
1076613227 |-15
1076613228 |-5
1076613229 |-5
1076613230 |-5
1076613231 |-5
1076613232 |-5
1076613233 |-5
1076613234 |-5
1076613235 |5
1076613236 |5
1076613237 |5
1076613238 |5
1076613239 |5
1076613240 |5
1076613241 |5
1076613242 |15
1076613243 |15
1076613244 |15
1076613245 |15
1076613246 |15
1076613247 |25
1076613248 |25
1076613249 |25
1076613250 |1.5069e-321
1076613251 |-30
1076613252 |-30
1076613253 |-30
1076613254 |-20
1076613255 |-20
1076613256 |-20
1076613257 |-20
1076613258 |-20
1076613259 |-10
1076613260 |-10
1076613261 |-10
1076613262 |-10
1076613263 |-10
1076613264 |-10
1076613265 |-10
1076613266 |0
1076613267 |0
1076613268 |0
1076613269 |0
1076613270 |0
1076613271 |0
1076613272 |0
1076613273 |10
1076613274 |10
1076613275 |10
1076613276 |10
1076613277 |10
1076613278 |10
1076613279 |10
1076613280 |20
1076613281 |20
1076613282 |20
1076613283 |20
1076613284 |20
1076613285 |30
1076613286 |30
1076613287 |30
1076613288 |1.5069e-321
1076613289 |-25
1076613290 |-25
1076613291 |-25
1076613292 |-15
1076613293 |-15
1076613294 |-15
1076613295 |-15
1076613296 |-15
1076613297 |-5
1076613298 |-5
1076613299 |-5
1076613300 |-5
1076613301 |-5
1076613302 |-5
1076613303 |-5
1076613304 |5
1076613305 |5
1076613306 |5
1076613307 |5
1076613308 |5
1076613309 |5
1076613310 |5
1076613311 |15
1076613312 |15
1076613313 |15
1076613314 |15
1076613315 |15
1076613316 |15
1076613317 |15
1076613318 |25
1076613319 |25
1076613320 |25
1076613321 |25
1076613322 |25
1076613323 |35
1076613324 |35
1076613325 |35
1076613326 |1.9812e-321
1076613327 |1.73124e-316
1076613328 |6.89873e-310
1076613329 |1.73396e-316
1076613330 |6.89873e-310
1076613331 |6.89873e-310
1076613332 |6.89873e-310
1076613333 |6.89873e-310
1076613334 |6.89873e-310
1076613335 |6.89873e-310
1076613336 |6.89873e-310
1076613337 |6.89873e-310
1076613338 |6.89873e-310
1076613339 |6.89873e-310
1076613340 |6.89873e-310
1076613341 |6.89873e-310
1076613342 |6.89873e-310
…goes on “forever”
[/code]

I’m not sure what this is, since I don’t understand why TTree::Draw would think it okay to overwrite allocated memory. #-o Would greatly appreciate if someone could figure out the source of the problem!

Hi,

Could you provide something we can run? Otherwise I’m afraid we cannot guess what’s wrong with your code…

Cheers, Bertrand.

Bellenot, here’s a main file I wrote called MinExample.cpp and the Cell class header and source files. This compiles and runs provided you have the root files needed in the MinExampleData folder, which is unfortunately too large for me to send here.

In any case, there is not problem with this minimal working example when I run it on my machine because it does not consume as much memory as the larger framework I usually run it in. I suspect this is a buffer overflow issue with TTree and it only occurs when so much memory is already written into the buffer. But I thought that this wouldn’t be allowed to happen.

Please let me know if you have any ideas.
Thanks,
Yelena
Cell.h (2.98 KB)
MinExample.cpp (2.1 KB)
Cell.cpp (10 KB)

Hi Yelena,

Then you should run valgrind on your application, something like:

valgrind --suppressions=$ROOTSYS/etc/valgrind-root.supp --num-callers=30 yourapplication

Cheers, Bertrand.

Hi Bertrand,

I’ve run valgrind on MinExample.cpp with the following command:

valgrind --suppressions=$ROOTSYS/etc/valgrind-root.supp --leak-check=yes --num-callers=30 --log-file="valgrindOUT.txt" ./MinExample

I’ve attached the output stream valgrindOUT.txt here along with the slightly updated code. It appears to be complaining quite a bit but I cannot determine whether these are benign complaints or indicate the root of the problem.

Thanks
Y
Cell.h (3 KB)
Cell.cpp (10.2 KB)
MinExample.cpp (2.11 KB)
valgrindOUT.txt (46.9 KB)

Maybe you can share your ROOT file through dropbox or sth similar

I’ve attached a much smaller file containing the Tree (identical structure). It still causes the program to crash/malfunction in some way when run inline with the larger software and the Tree::Draw function is invoked. I’ve also attached the MCPQMap001.root which contains the vectors loaded into the cell classes.
MCPQMap0001.root (11.6 KB)
OutTrees_He6_Diffuse_06172016_T0TOFCut_Triple.root (1.96 MB)

Hi,

Not sure if it will help, but could you try this:

//ROOT includes
#include "TApplication.h"
#include "TROOT.h"
#include "TStyle.h"
#include "TMath.h"
#include "TFile.h"
#include "TCanvas.h"
#include "TSpline.h"
#include "TTree.h"

int main(int argc, char* argv[])
{
  gROOT->SetBatch();  // prevent canvas to pop-up
  TApplication theApp("App", &argc, argv); 
  char *Direct;
  Direct=getenv("MIN_EXAMPLE_DIRECTORY");
  [...]

i.e. add a TApplication instance in your code (but no need to call run())

Cheers, Bertrand.

Hi Yelena,

The valgrind output does not show any real problem. Is the example you ran under valgrind failed without valgrind? When run with valgrind did it also show the odd behavior?

Looking at your code, I see nothing obvious that could lead to this kind of problem.

[quote]But I thought that this wouldn’t be allowed to happen.[/quote]and as far we know, it does not happen when TTree (and related) are used as intended.

This may or may not be the correct interpretation. Does the ‘minimal working example’ ever exhibits the problem? If not, then it is likely it is ‘missing’ the feature from the larger framework that lead to the problem (and just using ‘more’ memory is unlikely to the triggering cause).

So unfortunately, I am afraid that without a running reproducer we willl not be able to narrow it down :frowning:

Cheers,
Philippe.