Pointer member variable

I have a complicated data structure that I would like to read/write to a TFile. The main object contains two member variables, one of which has a pointer into the other. I can write the object to a TFile. However, when reading the object from file, the ROOT interpreter crashes with a “double free or corruption” error. Being unfamiliar with the way in which ROOT serializes TObjects, I cannot diagnose the issue any further, and so any help would be greatly appreciated.

Below is a minimal working example needed to cause the crash. This was compiled with version 5.34.09 of ROOT.

#include "TObject.h"

class SubStructureA : public TObject {
public:
  SubStructureA() : z(3) { }
  double z;

  ClassDef(SubStructureA, 1);
};

class SubStructureB : public TObject {
public:
  SubStructureB() : subA(NULL) { }
  SubStructureB(SubStructureA* subA) : subA(subA) { }
  SubStructureA* subA;

  ClassDef(SubStructureB, 1);
};



class DataStructure : public TObject{
public:
  DataStructure() : subB(&subA) { }

  SubStructureA subA;
  SubStructureB subB;
public:
  ClassDef(DataStructure,1);
};[/code]

The LinkDef file is as follows.

[code]
#ifdef __CINT__
#pragma link off all globals;
#pragma link off all classes;
#pragma link off all functions;
#pragma link C++ class DataStructure+;
#pragma link C++ class SubStructureA+;
#pragma link C++ class SubStructureB+;
#endif
[/code]

With these, the following test functions can first write to a TFile, then attempt to read from it.

[code]
void test_write() {
  gSystem->Load("libAnalysis");
  TFile* tfile = new TFile("test_out.root", "RECREATE");
  DataStructure* data = new DataStructure;
  data->Write("data");
  tfile->Close();
}

void test_read() {
  gSystem->Load("libAnalysis");
  TFile* tf = new TFile("test_out.root");
  DataStructure* data = (DataStructure*) tf->Get("data");
}
[/code]

The error messages printed out are as follows.
[code]*** glibc detected *** /mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/bin/root.exe: double free or corruption (out): 0x0000000000ef8990 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x76a16)[0x2ab63983ea16]
/lib/x86_64-linux-gnu/libc.so.6(cfree+0x6c)[0x2ab6398437bc]
/user/USERNAME/root_tests/pointer_test/./libAnalysis.so(_ZN13SubStructureAD0Ev+0x24)[0x2ab63aabe380]
/user/USERNAME/root_tests/pointer_test/./libAnalysis.so(+0x9771)[0x2ab63aab9771]
/mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/lib/libCore.so.5(_ZN6TClass10DestructorEPvb+0x50)[0x2ab637b4ad40]
/mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/lib/libRIO.so(_ZN11TBufferFile13ReadFastArrayEPPvPK6TClassibP15TMemberStreamerS4_+0x195)[0x2ab63af372f5]
/mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/lib/libRIO.so(_ZN13TStreamerInfo10ReadBufferIPPcEEiR7TBufferRKT_iiii+0x3eef)[0x2ab63af036df]
/mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/lib/libRIO.so(_ZN20TStreamerInfoActions17GenericReadActionER7TBufferPvPKNS_14TConfigurationE+0x3b)[0x2ab63ae0a6fb]
/mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/lib/libRIO.so(_ZN11TBufferFile13ApplySequenceERKN20TStreamerInfoActions15TActionSequenceEPv+0x75)[0x2ab63af35665]
/mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/lib/libRIO.so(_ZN11TBufferFile15ReadClassBufferEPK6TClassPvS2_+0xd1)[0x2ab63af31d21]
/user/USERNAME/root_tests/pointer_test/./libAnalysis.so(_ZN13SubStructureB8StreamerER7TBuffer+0x4b)[0x2ab63aab984d]
/mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/lib/libRIO.so(_ZN13TStreamerInfo10ReadBufferIPPcEEiR7TBufferRKT_iiii+0x5812)[0x2ab63af05002]
/mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/lib/libRIO.so(_ZN20TStreamerInfoActions17GenericReadActionER7TBufferPvPKNS_14TConfigurationE+0x3b)[0x2ab63ae0a6fb]
/mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/lib/libRIO.so(_ZN11TBufferFile13ApplySequenceERKN20TStreamerInfoActions15TActionSequenceEPv+0x75)[0x2ab63af35665]
/mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/lib/libRIO.so(_ZN11TBufferFile15ReadClassBufferEPK6TClassPvS2_+0xd1)[0x2ab63af31d21]
/user/USERNAME/root_tests/pointer_test/./libAnalysis.so(_ZN13DataStructure8StreamerER7TBuffer+0x4b)[0x2ab63aab9013]
/mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/lib/libRIO.so(_ZN4TKey7ReadObjEv+0x313)[0x2ab63ade9833]
/mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/lib/libRIO.so(_ZN14TDirectoryFile3GetEPKc+0x192)[0x2ab63adf8572]
/mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/lib/libCore.so.5(+0x334b25)[0x2ab6379bcb25]
/mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/lib/libCint.so.5(_ZN4Cint19G__ExceptionWrapperEPFiP8G__valuePKcP8G__paramiES1_PcS5_i+0x37)[0x2ab6380c9ae7]
/mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/lib/libCint.so.5(G__execute_call+0x61)[0x2ab638129301]
/mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/lib/libCint.so.5(G__call_cppfunc+0x27e)[0x2ab6381296ce]
/mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/lib/libCint.so.5(G__interpret_func+0x4819)[0x2ab638072e39]
/mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/lib/libCint.so.5(G__getfunction+0x1884)[0x2ab6380b51f4]
/mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/lib/libCint.so.5(_Z15G__getstructmemiR18G__FastAllocStringPciS1_PiP12G__var_arrayi+0x6dc)[0x2ab6380f4e6c]
/mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/lib/libCint.so.5(G__getvariable+0x45fb)[0x2ab6380edceb]
/mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/lib/libCint.so.5(G__getitem+0xdd)[0x2ab6381c667d]
/mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/lib/libCint.so.5(G__getexpr+0x54da)[0x2ab6381cd35a]
/mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/lib/libCint.so.5(G__getfunction+0x3aec)[0x2ab6380b745c]
/mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/lib/libCint.so.5(G__getitem+0x842)[0x2ab6381c6de2]
/mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/lib/libCint.so.5(G__getexpr+0x54da)[0x2ab6381cd35a]
/mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/lib/libCint.so.5(G__define_var+0x15f7)[0x2ab6381a8b37]
/mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/lib/libCint.so.5(G__exec_statement+0x21d3)[0x2ab6380bd173]
/mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/lib/libCint.so.5(G__interpret_func+0x297d)[0x2ab638070f9d]
/mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/lib/libCint.so.5(G__getfunction+0x18e9)[0x2ab6380b5259]
/mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/lib/libCint.so.5(G__getitem+0x842)[0x2ab6381c6de2]
/mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/lib/libCint.so.5(G__getexpr+0x54da)[0x2ab6381cd35a]
/mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/lib/libCint.so.5(G__calc_internal+0x3ad)[0x2ab6381d876d]
/mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/lib/libCint.so.5(G__process_cmd+0x2ac0)[0x2ab6380d8eb0]
/mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/lib/libCore.so.5(_ZN5TCint11ProcessLineEPKcPN12TInterpreter10EErrorCodeE+0x371)[0x2ab637b6aa91]
/mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/lib/libCore.so.5(_ZN12TApplication11ExecuteFileEPKcPib+0x79d)[0x2ab637be8fcd]
/mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/lib/libCore.so.5(_ZN12TApplication11ProcessLineEPKcbPi+0x73a)[0x2ab637be7d8a]
/mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/lib/libRint.so.5(_ZN5TRint3RunEb+0x3a9)[0x2ab638de9fa9]
/mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/bin/root.exe(main+0x4c)[0x40113c]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xfd)[0x2ab6397e6ead]
/mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/bin/root.exe[0x4011ad]
======= Memory map: ========
00400000-00402000 r-xp 00000000 00:26 95517257                           /mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/bin/root.exe
00601000-00602000 rw-p 00001000 00:26 95517257                           /mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/bin/root.exe
00ef0000-01692000 rw-p 00000000 00:00 0                                  [heap]
2ab637460000-2ab637480000 r-xp 00000000 08:01 4849886                    /lib/x86_64-linux-gnu/ld-2.13.so
2ab637480000-2ab637482000 rw-p 00000000 00:00 0
2ab63767f000-2ab637680000 r--p 0001f000 08:01 4849886                    /lib/x86_64-linux-gnu/ld-2.13.so
2ab637680000-2ab637681000 rw-p 00020000 08:01 4849886                    /lib/x86_64-linux-gnu/ld-2.13.so
2ab637681000-2ab637682000 rw-p 00000000 00:00 0
2ab637688000-2ab637d55000 r-xp 00000000 00:26 79922477                   /mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/lib/libCore.so.5.34.09
2ab637d55000-2ab637f54000 ---p 006cd000 00:26 79922477                   /mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/lib/libCore.so.5.34.09
2ab637f54000-2ab637f8a000 rw-p 006cc000 00:26 79922477                   /mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/lib/libCore.so.5.34.09
2ab637f8a000-2ab63800b000 rw-p 00000000 00:00 0
2ab638010000-2ab63824c000 r-xp 00000000 00:26 80909545                   /mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/lib/libCint.so.5.34.09
2ab63824c000-2ab63844b000 ---p 0023c000 00:26 80909545                   /mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/lib/libCint.so.5.34.09
2ab63844b000-2ab638453000 rw-p 0023b000 00:26 80909545                   /mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/lib/libCint.so.5.34.09
2ab638453000-2ab63898b000 rw-p 00000000 00:00 0
2ab638990000-2ab638bbc000 r-xp 00000000 00:26 72651294                   /mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/lib/libMathCore.so.5.34.09
2ab638bbc000-2ab638dbb000 ---p 0022c000 00:26 72651294                   /mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/lib/libMathCore.so.5.34.09
2ab638dbb000-2ab638dc8000 rw-p 0022b000 00:26 72651294                   /mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/lib/libMathCore.so.5.34.09
2ab638dc8000-2ab638dcf000 rw-p 00000000 00:00 0
2ab638dd0000-2ab638dfe000 r-xp 00000000 00:26 79922481                   /mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/lib/libRint.so.5.34.09
2ab638dfe000-2ab638ffd000 ---p 0002e000 00:26 79922481                   /mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/lib/libRint.so.5.34.09
2ab638ffd000-2ab639000000 rw-p 0002d000 00:26 79922481                   /mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/lib/libRint.so.5.34.09
2ab639001000-2ab639011000 rw-p 00000000 00:00 0
2ab63901a000-2ab63901b000 rw-p 00000000 00:00 0
2ab639020000-2ab639108000 r-xp 00000000 08:01 13635918                   /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.17
2ab639108000-2ab639308000 ---p 000e8000 08:01 13635918                   /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.17
2ab639308000-2ab639310000 r--p 000e8000 08:01 13635918                   /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.17
2ab639310000-2ab639312000 rw-p 000f0000 08:01 13635918                   /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.17
2ab639312000-2ab639327000 rw-p 00000000 00:00 0
2ab639328000-2ab6393a9000 r-xp 00000000 08:01 4849715                    /lib/x86_64-linux-gnu/libm-2.13.so
2ab6393a9000-2ab6395a8000 ---p 00081000 08:01 4849715                    /lib/x86_64-linux-gnu/libm-2.13.so
2ab6395a8000-2ab6395a9000 r--p 00080000 08:01 4849715                    /lib/x86_64-linux-gnu/libm-2.13.so
2ab6395a9000-2ab6395aa000 rw-p 00081000 08:01 4849715                    /lib/x86_64-linux-gnu/libm-2.13.so
2ab6395b0000-2ab6395c5000 r-xp 00000000 08:01 4849706                    /lib/x86_64-linux-gnu/libgcc_s.so.1
2ab6395c5000-2ab6397c5000 ---p 00015000 08:01 4849706                    /lib/x86_64-linux-gnu/libgcc_s.so.1
2ab6397c5000-2ab6397c6000 rw-p 00015000 08:01 4849706                    /lib/x86_64-linux-gnu/libgcc_s.so.1
2ab6397c6000-2ab6397c7000 rw-p 00000000 00:00 0
2ab6397c8000-2ab63994a000 r-xp 00000000 08:01 4849719                    /lib/x86_64-linux-gnu/libc-2.13.so
2ab63994a000-2ab639b4a000 ---p 00182000 08:01 4849719                    /lib/x86_64-linux-gnu/libc-2.13.so
2ab639b4a000-2ab639b4e000 r--p 00182000 08:01 4849719                    /lib/x86_64-linux-gnu/libc-2.13.so
2ab639b4e000-2ab639b4f000 rw-p 00186000 08:01 4849719                    /lib/x86_64-linux-gnu/libc-2.13.so
2ab639b4f000-2ab639b54000 rw-p 00000000 00:00 0
2ab639b58000-2ab639b94000 r-xp 00000000 08:01 4853621                    /lib/x86_64-linux-gnu/libpcre.so.3.13.1
2ab639b94000-2ab639d94000 ---p 0003c000 08:01 4853621                    /lib/x86_64-linux-gnu/libpcre.so.3.13.1
2ab639d94000-2ab639d95000 rw-p 0003c000 08:01 4853621                    /lib/x86_64-linux-gnu/libpcre.so.3.13.1
2ab639d98000-2ab639dae000 r-xp 00000000 08:01 4849803                    /lib/x86_64-linux-gnu/libz.so.1.2.7
2ab639dae000-2ab639fad000 ---p 00016000 08:01 4849803                    /lib/x86_64-linux-gnu/libz.so.1.2.7
2ab639fad000-2ab639fae000 r--p 00015000 08:01 4849803                    /lib/x86_64-linux-gnu/libz.so.1.2.7
2ab639fae000-2ab639faf000 rw-p 00016000 08:01 4849803                    /lib/x86_64-linux-gnu/libz.so.1.2.7
2ab639faf000-2ab639fb0000 rw-p 00000000 00:00 0
2ab639fb0000-2ab639fb2000 r-xp 00000000 08:01 4849723                    /lib/x86_64-linux-gnu/libdl-2.13.so
2ab639fb2000-2ab63a1b2000 ---p 00002000 08:01 4849723                    /lib/x86_64-linux-gnu/libdl-2.13.so
2ab63a1b2000-2ab63a1b3000 r--p 00002000 08:01 4849723                    /lib/x86_64-linux-gnu/libdl-2.13.so
2ab63a1b3000-2ab63a1b4000 rw-p 00003000 08:01 4849723                    /lib/x86_64-linux-gnu/libdl-2.13.so
2ab63a1b8000-2ab63a1cf000 r-xp 00000000 08:01 4849906                    /lib/x86_64-linux-gnu/libpthread-2.13.so
2ab63a1cf000-2ab63a3ce000 ---p 00017000 08:01 4849906                    /lib/x86_64-linux-gnu/libpthread-2.13.so
2ab63a3ce000-2ab63a3cf000 r--p 00016000 08:01 4849906                    /lib/x86_64-linux-gnu/libpthread-2.13.so
2ab63a3cf000-2ab63a3d0000 rw-p 00017000 08:01 4849906                    /lib/x86_64-linux-gnu/libpthread-2.13.so
2ab63a3d0000-2ab63a3d9000 rw-p 00000000 00:00 0
2ab63a3e0000-2ab63a3eb000 r-xp 00000000 08:01 4849709                    /lib/x86_64-linux-gnu/libnss_files-2.13.so
2ab63a3eb000-2ab63a5ea000 ---p 0000b000 08:01 4849709                    /lib/x86_64-linux-gnu/libnss_files-2.13.so
2ab63a5ea000-2ab63a5eb000 r--p 0000a000 08:01 4849709                    /lib/x86_64-linux-gnu/libnss_files-2.13.so
2ab63a5eb000-2ab63a5ec000 rw-p 0000b000 08:01 4849709                    /lib/x86_64-linux-gnu/libnss_files-2.13.so
2ab63a5f0000-2ab63a5fa000 r-xp 00000000 08:01 4849894                    /lib/x86_64-linux-gnu/libnss_nis-2.13.so
2ab63a5fa000-2ab63a7f9000 ---p 0000a000 08:01 4849894                    /lib/x86_64-linux-gnu/libnss_nis-2.13.so
2ab63a7f9000-2ab63a7fa000 r--p 00009000 08:01 4849894                    /lib/x86_64-linux-gnu/libnss_nis-2.13.so
2ab63a7fa000-2ab63a7fb000 rw-p 0000a000 08:01 4849894                    /lib/x86_64-linux-gnu/libnss_nis-2.13.so
2ab63a800000-2ab63a815000 r-xp 00000000 08:01 4849717                    /lib/x86_64-linux-gnu/libnsl-2.13.so
2ab63a815000-2ab63aa14000 ---p 00015000 08:01 4849717                    /lib/x86_64-linux-gnu/libnsl-2.13.so
2ab63aa14000-2ab63aa15000 r--p 00014000 08:01 4849717                    /lib/x86_64-linux-gnu/libnsl-2.13.so
2ab63aa15000-2ab63aa16000 rw-p 00015000 08:01 4849717                    /lib/x86_64-linux-gnu/libnsl-2.13.so
2ab63aa16000-2ab63aa1b000 rw-p 00000000 00:00 0
2ab63aa1c000-2ab63aaae000 rw-p 00000000 00:00 0
2ab63aab0000-2ab63aac1000 r-xp 00000000 00:25 85548081                   /user/USERNAME/root_tests/pointer_test/libAnalysis.so
2ab63aac1000-2ab63acc1000 ---p 00011000 00:25 85548081                   /user/USERNAME/root_tests/pointer_test/libAnalysis.so
2ab63acc1000-2ab63acc3000 rw-p 00011000 00:25 85548081                   /user/USERNAME/root_tests/pointer_test/libAnalysis.so
2ab63acc8000-2ab63afa7000 r-xp 00000000 00:26 85659704                   /mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/lib/libRIO.so.5.34.09
2ab63afa7000-2ab63b1a6000 ---p 002df000 00:26 85659704                   /mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/lib/libRIO.so.5.34.09
2ab63b1a6000-2ab63b1b4000 rw-p 002de000 00:26 85659704                   /mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/lib/libRIO.so.5.34.09
2ab63b1b4000-2ab63b1b7000 rw-p 00000000 00:00 0
2ab63b1b8000-2ab63b1fb000 r-xp 00000000 00:26 79922485                   /mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/lib/libThread.so.5.34.09
2ab63b1fb000-2ab63b3fb000 ---p 00043000 00:26 79922485                   /mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/lib/libThread.so.5.34.09
2ab63b3fb000-2ab63b3ff000 rw-p 00043000 00:26 79922485                   /mnt/misc/sw/x86_64/Debian/7/root/gnu/5.34.09/lib/libThread.so.5.34.09
2ab63b3ff000-2ab63b448000 rw-p 00000000 00:00 0
2ab63c000000-2ab63c021000 rw-p 00000000 00:00 0
2ab63c021000-2ab640000000 ---p 00000000 00:00 0
7ffff59b9000-7ffff5a15000 rw-p 00000000 00:00 0                          [stack]
7ffff5a60000-7ffff5a61000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]

The entire directory is included in the attached tarball. To compile and run the test that leads to the crash, run “make test” in the directory after unpacking.
pointer_test.tar.gz (983 Bytes)

Hi,

Since the pointer data member subA in the class SubStructureB is not decorated, ROOT (must) assume that it is pointer to another owner by SubStructureB and thus upon reading a new one will delete the old one. In your case this assumption is wrong.

Literally the value of this pointer is determine by the structure of the objects and storing its value in the byte stream is redundant. Thus the best solution is your case is to set the pointer to be transient.

[code]class SubStructureB : public TObject {
public:
SubStructureB() : subA(NULL) { }
SubStructureB(SubStructureA* subA) : subA(subA) { }
SubStructureA* subA; //! The exclamation mark indicates it is transient.

ClassDef(SubStructureB, 1);
};[/code]

Note that this solution work if and only if SubStructureB never owns its subA (which the lack of destructor indicates to be true).

Cheers,
Philippe.

Phillipe,

Thank you. That seems to work in this case. A few follow-up questions

[ul]
[li] My understanding of the “//!” syntax was that it marked the variable as not needing to be written to the ROOT file. With nothing written to the TFile, how does it know where the pointer should point?[/li]
[li] With the pointer marked as transient, I cannot draw parameters from it using TTree::Draw. Is there a way to do so?[/li][/ul]

I also realized that while I gave a description of the error I was seeing, I did not give a description of why I wanted to have this particular data structure. It may be that I am trying to solve the wrong problem. I have two different event types, here as SubStructureA and SubStructureB. Each of SubStructureB may be correlated with a SubStructureA, in which case additional parameters are calculated. I want to keep track of which SubStructureA was used to calculate those additional parameters.

[quote]My understanding of the “//!” syntax was that it marked the variable as not needing to be written to the ROOT file. With nothing written to the TFile, how does it know where the pointer should point?[/quote]In the example you gave earlier, this is ‘recorded’ by the sole constructor DataStructure() : subB(&subA) { }which is called whenever a ‘DataStructure’ object is created.

[quote]With the pointer marked as transient, I cannot draw parameters from it using TTree::Draw. Is there a way to do so?..I want to keep track of which SubStructureA was used to calculate those additional parameters.[/quote]It sounds like the example above is over simplified (No TTree, single parameter, single SubStructureA), could you provide a more complete example?

Thanks,
Philippe.

Phillipe,

I agree that I oversimplified the example. Below is an example that is closer to my full analysis code. The tarball containing the code is attached to this post.

Here is the new DataStructure. It has a vector of SubStructureA and of SubStructureB that it owns. SubStructureB has a list of derived information from SubStructureA, should a pointer to a SubStructureA be passed in.

#include <vector>

#include "TObject.h"

class SubStructureA : public TObject {
public:
  SubStructureA() : x(0) { }
  double x;
  double a;

  ClassDef(SubStructureA, 1);
};

struct DerivedInfo : public TObject {
  DerivedInfo() : source(NULL), z(0) { }
  SubStructureA* source;
  double z;

  ClassDef(DerivedInfo, 1);
};

class SubStructureB : public TObject {
public:
  SubStructureB() { }
  double y;

  void UseSubStructureA(SubStructureA* subA){
    DerivedInfo new_derived;
    new_derived.source = subA;
    new_derived.z = subA->x + y;
    derived.push_back(new_derived);
  }

  std::vector<DerivedInfo> derived;

  ClassDef(SubStructureB, 1);
};

class DataStructure : public TObject{
public:
  DataStructure() { }
  virtual ~DataStructure() {
    Clear();
  }

  void Clear(){
    for(unsigned int i=0; i<subA.size(); i++){
      delete subA[i];
    }
    subA.clear();
    for(unsigned int i=0; i<subB.size(); i++){
      delete subB[i];
    }
    subB.clear();
  }

  std::vector<SubStructureA*> subA;
  std::vector<SubStructureB*> subB;

public:
  ClassDef(DataStructure,1);
};

The writing of these to a TTree is now as follows. Each SubStructureA and SubStructureB are filled with random values, then some of the SubStructureA are passed to the SubStructureB to be used in generating DerivedInfo.

void test_write(){
  gSystem->Load("libAnalysis");
  TFile* tfile = new TFile("test_out.root", "RECREATE");
  TTree* t = new TTree("t", "Example Data");
  DataStructure* data = new DataStructure;
  t->Branch("data", &data);

  for(int iEvent=0; iEvent<100; iEvent++){
    data->Clear();

    // Generate some random data.
    for(int i=0; i<5; i++){
      SubStructureA* subA = new SubStructureA;
      subA->x = rand()%5;
      subA->a = subA->x + 15;
      data->subA.push_back(subA);
    }

    for(int i=0; i<5; i++){
      SubStructureB* subB = new SubStructureB;
      subB->y = 15 + rand()%5;
      data->subB.push_back(subB);
    }

    // Generate the derived data
    for(int i=0; i<data->subA.size(); i++){
      for(int j=0; j<data->subB.size(); j++){
        if ( rand() % 3 ){ // Not every SubStructureA gets correlated with every SubStructureB
          SubStructureA* subA = data->subA[i];
          SubStructureB* subB = data->subB[i];
          subB->UseSubStructureA(subA);
        }
      }
    }

    t->Fill();
  }

  t->Write();
  tfile->Close();
}

For testing the reading from the TTree, I have the following code. This first tests several different histograms, both within the different SubStrucutres, and between the “correlated” SubStructures. Finally, it tests whether there is duplication in memory of the SubStructureA pointers held by the DerivedInfo class.

void test_read(){
  gSystem->Load("libAnalysis");
  TFile* tf = new TFile("test_out.root");
  TTree* t = (TTree*) tf->Get("t");

  // Test drawing the histograms
  TCanvas* c1 = new TCanvas;
  c1->Divide(1,4);
  c1->cd(1);
  t->Draw("data.subA.x >> hstX");
  c1->cd(2);
  t->Draw("data.subB.y >> hstY");
  c1->cd(3);
  t->Draw("data.subB.derived.z >> hstZ");
  c1->cd(4);
  t->Draw("data.subB.derived.z : data.subB.derived.source.a >> hstZA");

  // Test that the pointers are
  DataStructure* data = new DataStructure;
  t->SetBranchAddress("data", &data);
  t->GetEntry(0);
  for(int i=0; i<data->subB.size(); i++){

    for(int j=0; j<data->subB[i]->derived.size(); j++){
      SubStructureA* source = data->subB[i]->derived[j].source;

      // Check that source came from data->subA.
      bool found = false;
      for(int k=0; k<data->subA.size(); k++){
        if(source == data->subA[k]){
          bool found = true;
          break;
        }
      }
      if(!found){
        std::cout << "Pointer pointed to different object" << std::endl;
      }

    }

  }
}

If I place a “//!” comment after the “SubStructureA* source;” declaration in DerivedInfo, then I cannot draw the last histogram, as it refers to the “source” variable, and the source variable holds a null pointer. If I do not place a “//!” comment, then the SubStructureA referred to by DerivedInfo and the SubStructureA held by DataStructure are not the same object.

Thank you very much for your help.
pointer_test.tar.gz (1.73 KB)

Hi,

You have three options: SubStructureA* source; //->which indicates that the pointee should not be reallocated by the I/O (unless source is null) but this will lead to a default constructed SubStructureA being written to the file if source is zero.
or

or

Cheers,
Philippe.