I would like to know how memory is allocated and freed for variable length array when reading a class from a TTree.
I attached a sample code.
When I run the sample code (you can run it just typing “make”), it crashes.
*** Break *** segmentation violation
Attaching to program: /proc/20401/exe, process 20401
[Thread debugging using libthread_db enabled]
[New Thread 0x2ba5680ac760 (LWP 20401)]
0x0000003939699335 in waitpid () from /lib64/libc.so.6
#1 0x000000393963c2e1 in do_system () from /lib64/libc.so.6
#2 0x00002ba564253b46 in TUnixSystem::StackTrace (this=0x36e43e0)
#3 0x00002ba564251123 in TUnixSystem::DispatchSignals (this=0x36e43e0,
sig=<value optimized out>) at core/unix/src/TUnixSystem.cxx:1099
#4 <signal handler called>
#5 0x00002ba565686012 in TStreamerInfo::ReadBufferSkip<char**> (
this=0x3796cc0, b=@0x3a026f0, arr=@0x7fff46abe248,
i=<value optimized out>, kase=<value optimized out>,
aElement=<value optimized out>, narr=1, eoffset=0)
#6 0x00002ba5656babf0 in TStreamerInfo::ReadBuffer<char**> (this=0x3796cc0,
b=@0x3a026f0, arr=@0x7fff46abe248, first=3, narr=1, eoffset=0, arrayMode=0)
#7 0x00002ba566b6e5bf in TBranchElement::ReadLeaves (this=0x39f58e0,
b=@0x3a026f0) at tree/tree/src/TBranchElement.cxx:3213
#8 0x00002ba566b65883 in TBranch::GetEntry (this=0x39f58e0, entry=0,
getall=<value optimized out>) at tree/tree/src/TBranch.cxx:1224
#9 0x00002ba566b6b635 in TBranchElement::GetEntry (this=0x39f58e0, entry=0,
getall=0) at tree/tree/src/TBranchElement.cxx:1868
#10 0x00002ba566b6b5f7 in TBranchElement::GetEntry (this=0x3992be0, entry=0,
getall=0) at tree/tree/src/TBranchElement.cxx:1851
#11 0x00002ba566bb1403 in TTree::GetEntry (this=0x387cca0, entry=0, getall=0)
#12 0x0000000000404b11 in main (argc=<value optimized out>,
argv=<value optimized out>) at testclass2.cc:16
My environment is ROOT v.5.22.00b, AMD64, linux 2.6, GCC4.1.
It is because old definition of this class(myclass1.h) has a data member “g”, but a new structure(myclass2.h) does not have it.
I expected that automatic schema evolution can take care about this kind of changes.
Is there any way to avoid the crash ?
The second question is what is the correct way to implement a function to resize a variable length array.
In my resize function (SeteSize in myclass1.h), it frees old memory when current pointer address is not NULL, and assign a new address with calling “new”.
When new size is 0, it only frees the memory and assign NULL to the pointer.
What I would like to know is what happens when the class is read from a TTree.
Apparently, ROOT does not set the pointer to be NULL even when the size specifier(in this example “n”) is 0.
In this case, should I free the memory when I want to resize it after TTree::GetEntry, or the memory is already freed by TTree ?
If TTree frees the memory but doesn’t change the pointer address, I could set pointer(“e” in this example) to be NULL when “n” is zero by hand, not to cause double free in the destructor.
If it is the case, the third question is how should I do for “f”, which is not present in the old structure, but is in the new structure.
It looks that TTree does not do anything for “f” when reading a TTree in this sample code. So if I set it to be NULL by hand when “n” is zero, it makes a memory leak.
So my problem in this example is, when “n” is zero, it seems that I should set “e” to be NULL by hand, but I should not change “f” by hand.
And I don’t find a way to know if “f” is defined in the steamer stored in the TTree.
If there is a way to know that “f” is a new member and does not exist in the TTree, I could do different handling for “e” and “f”.
(Suppose the structure can be changed frequently by another collaborator but not me. So I may not know that the structure was changed.)
I appreciate any help.
treetest.tar.gz (1.52 KB)