Add a branch to an existing tree in another .cc file

Hello,
I meet a problem when I use root.

I write a file to add a branch to an existing tree,
and save it in main function.
I declare all variable are global.
But when proceeding to wf->cd(); wf->close();
the program meet errors.

in add.cc

int add(){

  std::cout << "Now in file : " << __FILE__ << ", function : " << __PRETTY_FUNCTION__ << ", line : " << __LINE__ << std::endl;

  Float_t x, y, z, sum;

  gv::rf = TFile::Open("test.root", "update");
  gv::trec = (TTree *)gv::rf->Get("trec");
  
  gv::branch = gv::trec->Branch("sum", &sum, "sum/F");

  gv::trec->SetBranchAddress("x", &x);
  gv::trec->SetBranchAddress("y", &y);
  gv::trec->SetBranchAddress("z", &z);

  Long64_t nentries = gv::trec->GetEntries();
  for(Long64_t ientry = 0; ientry < nentries; ++ientry){
    gv::trec->GetEntry(ientry);

    sum = x +y +z;

    gv::branch->Fill();
  }

  return 0;
}

in main.cc

int main(){

  add();

  gv::rf->cd();
  gv::trec->Write("", TObject::kOverwrite); // save only the new version of the tree
  gv::rf->Close();

}

how to solve it? May I pass the file pointer to functionf add?

Thank you very much.

By the way, I find write root function in different .cc files, for example open a file in a .cc file and close in another .cc file, is very nuisance, I could not find examples in the website.


Please read tips for efficient and successful posting and posting code

ROOT Version: Not Provided
Platform: Not Provided
Compiler: Not Provided


When attaching local variable to a TTree:

int add(){
....
  Float_t x, y, z, sum;
...
  gv::trec->SetBranchAddress("x", &x);
  gv::trec->SetBranchAddress("y", &y);
  gv::trec->SetBranchAddress("z", &z);
...

at the end of the function you must either be ‘done’ (i.e. never use again or even delete) with the TTree
or call

  gv::trec->ResetBranchAddresses();

otherwise, when using the TTree it will *still* use those address and thus (potentially) corrupt the stack (and crash your program).

all you need is:

int main(){

  add();

  gv::rf->Write(TObject::kOverwrite); // save only the new version of the tree
  delete gv::rf;
}

I do not quite understand. In your example (so far) there is no need to do the read/update and the write in 2 different cc files. Why do you have this separation?

A little advertising for a new features. Since v6.14 we recommend using:

    gv::branch->BackFill();

When adding a branch to an existing TTree so that this new branch is properly clustered (matching the rest of the TTree).

Cheers,
Philippe.

Dear Philippe,
It works. Thanks.

My original code is quite long, so that reading it is boring.
Therefore to make my code clear, I would like to write various files to carry out different functions.

for example,
one is to open file to read and get TTrees and histograms inside
one is to open file to write and declare new TTrees and histograms
one is to perform the calculation using entries in TTrees and histograms
one is to close all the files

I do not want to write all of them in one file and even in a function.

Therefore I want both TTree and histogram, even TFile object, could be passed as parameters to the functions.
I find both TTree and histogram are attached to the currrent directory.

I read section Input/Output 1.2.8:

When a variable is declared on the stack in a function such as in the code below, it will be deleted when it goes out of scope.

Creating it on the heap instead of on the stack could prevent an object in a function from being deleted when it goes out of scope.

But I meet errors when I open a TFile in one file and close in main function.

The method you suggest is ok.

Thank you very much.