Closed YanzhaoW closed 4 months ago
Thanks for analyzing this!
(We came to an alike result).
Our quick fix would be to replace the std::vector
by a std::list
. This is probably the fix that we would like to deploy for 19.0.1.
Hi, @ChristianTackeGSI
I don't quite understand the purpose of fObj2
. When you call GetObject
, if the branch has not been added and does't exist in the tree, you push nullptr
to the vector. If the branch exists, you push the same pointer twice into the vector. On the other hand, you also have fMap
for the book-keeping of the branches.
Right, fObj2
is a bit strange!
We would like to have a minimal fix for 19.0.1 first. And the minimal one is to use std::list
.
For 19.1 we can then slowly work on further refactoring and improving GetObject.
And: Thanks for the reference to TTreeReader!
Ok, Fair enough.
Should I close this PR and you create another one using std::list
? Or I should just change it to std::list
here?
Ok, Fair enough.
Should I close this PR and you create another one using
std::list
? Or I should just change it tostd::list
here?
How ever you like. :-)
@dennisklein wanted to create a proper test first anyway.
@ChristianTackeGSI
Is this minimum change OK for you?
There is another issue about branch IO of FairRootManger:
There are two different, independent branch registries: fAnyBranchMap
and fMap
. These are used by different APIs of FairRootManager:
fAnyBranchMap
is used by RegisterAny
and InitObjectAs
.fMap
is used by Register
and GetObject
. Any branch registered in one way cannot be read by another way.
What's even more "interesting" is that the event header (online run) is always registered in fMap
but not in fAnyBranchMap
. So you may find that you can get a valid event header from GetObject
but mysteriously nullptr from InitObjectAs
.
@ChristianTackeGSI @dennisklein
It looks like it will take a bit longer to create proper tests for this. So merging now, so that the fix is in place at least.
BTW: I think, we need a ChangeLog entry for this?
Describe your proposal.
Fix the UB found in the issue #1556 related to
FairRootManager::GetObject
.Cause of the issue
The branch address of the TTree must be fixed during the data reading. In other words, if an object of type
T
needs to be read from a tree, the valueT**
must be fixed and cannot be changed during the whole reading process. However, in the GetObject function, the variablenewentry
is a reference to theT*
pointer stored in thestd::vector<T*>
. If the size of the vector grows beyond its capacity, the whole vector will be moved to another memory location, which means theT**
value will be changed.This makes sense as in my real practice from R3BRoot, I didn't get all zeros but rather direct segmentation fault.
Let
newentry
refer to theT*
in the object ofstd::map<TString, TObject*>
fixes the issue.std::map
doesn't reallocate its entries during the runtime.TODO
AddMemoryBranch
now returnsTObject*&
, which is ugly and asking for troubles in the future. Unfortunately, there isn't any better way to deal with this issue if we still use TTree raw API for the data reading. It must take aTObject**
for callingSetBranchAddress
.TTreeReader
is a much better choice as we don't need to deal withT**
situation anymore.Checklist: