Hello I have a Ntuple with Float arrays with variable size for each ntuple event.
So I decided to first dicover the size, and after that dynamically allocate the arrays and
fill with SetBranchAddress / GetEntry. It works well for the 1st ntuple event, but crashes for the 2…
Any idea?
DVNtuples.root (1.48 MB)
dp.C (3.17 KB)
Hi,
Your code looks like:[code]TTree t=(TTree)f->Get(“B2pipipi”);
TTree tn=(TTree)f->Get(“B2pipipi”);
for (Int_t i=1; i < tn->GetEntries() ; i++) {
tn->SetBranchAddress(“nCand”,&ncand);
tn->GetEntry(i);
t->ResetBranchAddresses();
p_1=new Float_t[ncand];
t->SetBranchAddress("p_lab1",p_1);
t->GetEntry(i);
delete[] p_1;
}[/code]First, this result is t and tn to point to the same TTree object. Then on the second loop, the TTree still contains a reference to p_1 which is deleted at the end of the first loop. Since you try to load the full entry “tn->GetEntry(i)” this result in the TTree writing to deleted memory … which leads to a crash.
In practice if the memory you assign to a TTree branch is deleted (either explicitly or because it was on the stack) you must reset the branch address (unless you know for sure it wont be used).
So you should have:[code]TTree t=(TTree)f->Get(“B2pipipi”);
for (Int_t i=1; i < tn->GetEntries() ; i++) {
t->SetBranchAddress(“nCand”,&ncand);
t->GetEntry(i);
p_1=new Float_t[ncand];
t->SetBranchAddress("p_lab1",p_1);
t->GetEntry(i);
t->ResetBranchAddresses();
delete[] p_1;
}[/code]Then you can improve the performance of your first read by reading only the branch you need:
[code]TTree t=(TTree)f->Get(“B2pipipi”);
TBranch *bCand = 0;
for (Int_t i=1; i < tn->GetEntries() ; i++) {
tn->SetBranchAddress(“nCand”,&ncand,&bCand);
bCand->GetEntry(i);
p_1=new Float_t[ncand];
t->SetBranchAddress("p_lab1",p_1);
t->GetEntry(i);
t->ResetBranchAddresses();
delete[] p_1;
}[/code]
Cheers,
Philippe
yes, now it works, thanks!