I’m trying to save a vector of a custom class using podio. The custom class is a class with only POD types (see below). I have reduced the code to the following (main.cpp
):
using namespace std;
#include "ExampleHitData.h"
#include "TTree.h"
#include "TFile.h"
#include <vector>
#include <iostream>
int main () {
ExampleHitData h {1, 2, 3, 4, 5};
vector<ExampleHitData> v {h};
TFile f("test.root", "RECREATE");
TTree tree("test", "tree");
void* ptr = &v;
auto vptr = (std::vector<ExampleHitData>*)ptr;
std::cout << "Size is " << vptr->size() << std::endl;
std::cout << (*vptr)[0].cellID << " " << (*vptr)[0].x << " " << (*vptr)[0].y << " " << (*vptr)[0].z << " " << (*vptr)[0].energy << std::endl;
tree.Branch("events", "std::vector<ExampleHitData>", ptr);
// tree.Branch("events", "std::vector<ExampleHitData>", vptr); // This works fine
tree.Fill();
tree.Write();
}
The issue here is that when passing the void* ptr
to tree.Branch
, it will crash when filling but when passing the std::vector<ExampleHitData>*
it works fine and the resulting file has all the fields with the expected values. The output of the cout
s is:
Size is 1
1 2 3 4 5
Full stack trace:
#0 0x00007fdc8d6ea707 in wait4 () from /usr/lib/libc.so.6
#1 0x00007fdc8d6627fb in ?? () from /usr/lib/libc.so.6
#2 0x00007fdc8f2eff29 in TUnixSystem::Exec (shellcmd=<optimized out>, this=0x559b3402d090) at /tmp/jmcarcell/spack-stage/spack-stage-root-master-t3bu3cb4mqxacnsbp2lifz3xukgested/spack-src/core/unix/src/TUnixSystem.cxx:2104
#3 TUnixSystem::StackTrace (this=0x559b3402d090) at /tmp/jmcarcell/spack-stage/spack-stage-root-master-t3bu3cb4mqxacnsbp2lifz3xukgested/spack-src/core/unix/src/TUnixSystem.cxx:2395
#4 0x00007fdc8f2ef8a4 in TUnixSystem::DispatchSignals (this=0x559b3402d090, sig=kSigSegmentationViolation) at /tmp/jmcarcell/spack-stage/spack-stage-root-master-t3bu3cb4mqxacnsbp2lifz3xukgested/spack-src/core/unix/src/TUnixSystem.cxx:3615
#5 <signal handler called>
#6 0x00007fdc8ebf0eec in TStreamerInfoActions::VectorLooper::WriteBasicType<unsigned long long> (buf=..., iter=0x1, end=0x4000000000000000, loopconfig=<optimized out>, config=<optimized out>) at /tmp/jmcarcell/spack-stage/spack-stage-root-master-t3bu3cb4mqxacnsbp2lifz3xukgested/spack-src/io/io/src/TStreamerInfoActions.cxx:1815
#7 0x00007fdc8eae789c in TStreamerInfoActions::TConfiguredAction::operator() (loopconf=0x559b3535d940, end_collection=0x4000000000000000, start_collection=0x1, buffer=..., this=0x559b3535d910) at /tmp/jmcarcell/spack-stage/spack-stage-root-master-t3bu3cb4mqxacnsbp2lifz3xukgested/spack-src/io/io/inc/TStreamerInfoActions.h:131
#8 TBufferFile::ApplySequence (this=0x559b3536f830, sequence=..., start_collection=0x1, end_collection=0x4000000000000000) at /tmp/jmcarcell/spack-stage/spack-stage-root-master-t3bu3cb4mqxacnsbp2lifz3xukgested/spack-src/io/io/src/TBufferFile.cxx:3646
#9 0x00007fdc8e3182ce in TBranchElement::FillLeavesCollectionMember (this=0x559b35359cb0, b=...) at /tmp/jmcarcell/spack-stage/spack-stage-root-master-t3bu3cb4mqxacnsbp2lifz3xukgested/spack-src/tree/tree/src/TBranchElement.cxx:1553
#10 0x00007fdc8e30f2b4 in TBranch::FillImpl (this=this
entry=0x559b35359cb0, imtHelper=imtHelper
entry=0x0) at /tmp/jmcarcell/spack-stage/spack-stage-root-master-t3bu3cb4mqxacnsbp2lifz3xukgested/spack-src/tree/tree/src/TBranch.cxx:893
#11 0x00007fdc8e31b85d in TBranchElement::FillImpl (this=0x559b35359cb0, imtHelper=0x0) at /tmp/jmcarcell/spack-stage/spack-stage-root-master-t3bu3cb4mqxacnsbp2lifz3xukgested/spack-src/tree/tree/src/TBranchElement.cxx:1265
#12 0x00007fdc8e31b5a6 in TBranchElement::FillImpl (this=0x559b3534cd50, imtHelper=0x0) at /tmp/jmcarcell/spack-stage/spack-stage-root-master-t3bu3cb4mqxacnsbp2lifz3xukgested/spack-src/tree/tree/src/TBranchElement.cxx:1290
#13 0x00007fdc8e387bb7 in TTree::Fill (this=0x7fff75fdd230) at /tmp/jmcarcell/spack-stage/spack-stage-root-master-t3bu3cb4mqxacnsbp2lifz3xukgested/spack-src/tree/tree/src/TTree.cxx:4609
It fails at TStreamerInfoActions::VectorLooper::WriteBasicType<unsigned long long>
because unsigned long long
is the type of the first member cellID
in the ExampleHitData
class.
I’m not sure if it’s a bug in ROOT but if ptr
is a well defined void*
to a vector why shouldn’t it work when the vector pointer vptr
works?
To reproduce you need ExampleHitData.h
:
class ExampleHitData {
public:
unsigned long long cellID; ///< cellID
double x; ///< x-coordinate
double y; ///< y-coordinate
double z; ///< z-coordinate
double energy; ///< measured energy deposit
};
and LinkDef.h
#ifdef __CLING__
#pragma link C++ class ExampleHitData;
#pragma link C++ class std::vector<ExampleHitData>;
#endif
and then run
rootcling -f ExampleHitData.cxx ExampleHitData.h LinkDef.h
gcc -c ExampleHitData.cxx -fPIC
gcc -shared -o libExampleHitData.so ExampleHitData.o
$(root-config --cxx --cflags --glibs) -L$PWD -lExampleHitData main.cpp
./a.out
ROOT Version: 6.28.00, 6.26.00 and also master from ~1 week ago
Platform: Centos7 and Arch Linux
Compiler: gcc 11.2.0 and 12.2.1