Rules to delete pointers for memory leakage

Hi,

This may be an old question but I still do not really understand this issue in ROOT and can only find fragment answers.

My questions are that

  1. when I create a pointer using new, what are the rules for me to delete the pointer? In c++, we always clean the pinter and may use smart pointer. I noticed that in ROOT macros, this is not always true. Another case if I use ROOT classes in my c++ program, what are the rules there?

  2. What if I have an container with pointer as element? Is there any differences between ROOT macros and application?

Many thanks for your clarifications.

regards,

gma

Hi,

The rules for memory management are the same for macro and C++ (except that using smart pointer is a bit harder in interpreted code).

[quote]what are the rules for me to delete the pointer?[/quote]The rule (and that is true for any C++ code/library) depend on what is the type you are pointed to. The rules regarding the ROOT classes are details in the object ownership chapter of the ROOT Users’ Guide (For example a TTree object will be attached to the TFile it’s data is store in and deleting the TFile will delete the TTree object hence making the explicit deletion of the TTree uncessary).

Cheers,
Philippe.

Hi, Philippe,
Thank for your answers. I was thinking that ROOT environment has some garbage collector,so macro users don’t care about the undeleted pointers. I was wrong and will take a look at the ownership chapter again.

Would you mind explaining how Tfile can own a TTree? For example, you can have a file in c++ and you can write string to file, but file and string are two different objects. Thanks.

regards,

gma

Hi,

[quote]Would you mind explaining how Tfile can own a TTree?[/quote]This should be detailed in the ‘Object Ownership’ chapter of the User’s Guide. Let me know if it still unclear after reading it.

Cheers,
Philippe

Hi, Phillipe,

Thanks. My question is more about why ROOT designs that way such that TFiles owns a TTree. It must has some benefits which I don’t appreciate yet. But I can feel the burden to memorize these new rules in addition all the exceptions in c++! :wink:

Anyway I will read that chapter.

regards,

gma

Hi,

[quote]why ROOT designs that way such that TFiles owns a TTree.[/quote]This is to simplify the most common interactive
use which ‘just’ need to be:root [] f = new TFile(...); mytree->Draw("variables"); somehisto->Draw("..."); .... delete f;(i.e. saving the keeping track of the histograms and trees extracted from the file).

Cheers,
Philippe.

Hi, Phillipe,

Do you mean user may delete file first, then delete tree which screws the program. It makes sense now to me that we have to add some layers for interactive usage of c++. Many thanks.

regards,

gma

Hi, Philippe,

Still not sure about the pointer deletion rule.

For example, in the following code


void Plotx()
{
  TFile *f = new TFile("$HOME/Desktop/test.root");
  TTree * T = (TTree*) f->Get("T");
  
  Double_t Close;
  T->SetBranchAddress("Close",&Close);
  
  Double_t* timeidx;
  Double_t* x;
  Int_t nentry = (Int_t)T->GetEntries();
  timeidx = new Int_t[nentry];
  x = new Double_t[nentry];
  
  for (Int_t i=0; i<nentry;i++)
  {
   T->GetEntry(i); 
   //cout<<Close<<endl;
   x[i]=Close;
   //cout<<"x_i is "<<x[i]<<endl;
   timeidx[i]= (Double_t)i;
  }
  
  //cout << x[10]<<endl;
  //cout << timeidx[10]<<endl;
  TGraph * gr = new TGraph(nentry,timeidx,x);
  
  //TCanvas *c1 = new TCanvas("c1","Graph options",200,10,600,400);
  gr->Draw("test");
  
  
  delete f;
  delete [] timeidx;
  delete [] x;
  timeidx =0;
  x = 0;
}

In the last four lines, I am going to clean the allocated memory. But I got the error message of

[quote]*** glibc detected *** /usr/local/root/bin/root.exe: double free or corruption (!prev): 0x000000000207a1e0 ***
======= Backtrace: =========
/lib/libc.so.6[0x7f4e1f069cb8]
/lib/libc.so.6(cfree+0x76)[0x7f4e1f06c276]
/usr/local/root/lib/libCint.so(G__delete_operator+0x655)[0x7f4e20650d85]
/usr/local/root/lib/libCint.so(G__exec_statement+0xa7eb)[0x7f4e2068961b]
/usr/local/root/lib/libCint.so(G__interpret_func+0x3644)[0x7f4e20634944]
/usr/local/root/lib/libCint.so(G__getfunction+0x24cc)[0x7f4e2062379c]
/usr/local/root/lib/libCint.so(G__getitem+0x802)[0x7f4e205f6b62]
/usr/local/root/lib/libCint.so(G__getexpr+0x46ef)[0x7f4e205fc29f]
/usr/local/root/lib/libCint.so(G__exec_statement+0xc278)[0x7f4e2068b0a8]
/usr/local/root/lib/libCint.so[0x7f4e205e270e]
/usr/local/root/lib/libCint.so(G__exec_tempfile_fp+0xe)[0x7f4e
[/quote]

I am curious why this is the case. Many thanks.

regards,

gma

Replace the line
timeidx = new Int_t[nentry];
by
timeidx = new Double_t[nentry]; //see your declaration

Rene

Thanks, Brun. it fixed the problems. Int_x timeidx was my old way data type for timeidx and I did not change it. :blush:

regards,

gma