Safe/correct way to output unique_ptr<TObject>?

Hello,
I have a c++ class that derives from TObject. I want to write it out to a branch in a file, but when I produce it I do so as a vector<unique_ptr<MyClass>> (the cluList below), and to complicate matters it contains a vector<unique_ptr<TObject>> (the hitVector below) as a member variable.
I am running in the ATLAS Athena framework, and everything appears fine when looping over the events, but the job crashes at the end (when releasing the memory) and the branch is not produced in the output root file. I suspect I as the unique_ptrs are going out of scope I am not allowed to output the variable.
Is there a correct way to do this? Or (as I suspect) should I not even be trying to to do this?
Cheers,
Al

/*
  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
*/

#ifndef HTTCLUSTER_H
#define HTTCLUSTER_H

#include <TObject.h>

#include <vector>
#include <map>
#include <iostream>
#include <sstream>
#include <memory>
#include "TrigHTTObjects/HTTRawHit.h"

// Extra helpers for clustering raw hits
// Switching to unique pointers to mitigate memory issues.
typedef std::vector<std::unique_ptr<HTTRawHit>> hitVector;
typedef std::map<unsigned int, hitVector> hitsByModuleMap;
class HTTCluster : public TObject {
   public:
      HTTCluster();
      hitVector hitlist; // list of hits that make the cluster
      HTTRawHit clusterEquiv; // hit equivalent to the cluster
      HTTRawHit seed; // hit equivalent to the cluster
      bool isSafe; // confirmed by ganged pattern recognition 
      bool isKilled; // ganged pattern recognition suggest to remove this cluster
      virtual ~HTTCluster();

      ClassDef(HTTCluster, 1);
};

typedef std::vector<std::unique_ptr<HTTCluster>> cluList;
typedef std::map<unsigned int, cluList> clustersByModuleMap;

#endif // HTTCLUSTER_H

ROOT Version: 6.08.06
Platform: CentOS, 7.6.1810
Compiler: cmake 3.11.0


Did you generate the dictionary for std::vector<std::unique_ptr<HTTCluster>> and std::map<unsigned int, cluList> ?

Were you able to run the failing example with valgrind to pin-point the cause of the double delete?

Hello,
I had indeed missed the #pragma for the map, and had accidentally left the vector entry as a standard pointer.
Adding these I now shift the error to the moment it tries to write to the file. A bit of the seg…

12:19:46  0x7f4a78426be9 CoreDumpSvcHandler::action(int, siginfo*, void*) ??:0   + 0xe9 [/cvmfs/atlas.cern.ch/repo/sw/software/21.0/Athena/21.0.66/InstallArea/x86_64-slc6-gcc62-opt/lib/libAthenaServices.so D[0x1dabe9]]
12:19:46  0x7f4a8d7985d0 __restore_rt ??:0   + 0x7f4a8d7985d0 [/lib64/libpthread.so.0 D[0xf5d0]]
12:19:47  0x7f4a671a4958 TInstrumentedIsAProxy<HTTCluster>::operator()(void const*) /cvmfs/atlas.cern.ch/repo/sw/software/21.0/sw/lcg/releases/ROOT/6.08.06-c8fb4/x86_64-slc6-gcc62-opt/include/TIsAProxy.h:86   + 0x8 [/afs/cern.ch/work/m/martyniu/HTT/ITK-buil\
d/x86_64-centos7-gcc62-opt/lib/libTrigHTTObjectsLib.so D[0x97958]]
12:19:47  0x7f4a8680ce57 TClass::GetActualClass(void const*) const ??:0   + 0x27 [/cvmfs/atlas.cern.ch/repo/sw/software/21.0/sw/lcg/releases/LCG_88/ROOT/6.08.06/x86_64-slc6-gcc62-opt/lib/libCore.so D[0x286e57]]
12:19:47  0x7f4a86e89e2d TBufferFile::WriteObjectAny(void const*, TClass const*) ??:0   + 0x2d [/cvmfs/atlas.cern.ch/repo/sw/software/21.0/sw/lcg/releases/LCG_88/ROOT/6.08.06/x86_64-slc6-gcc62-opt/lib/libRIO.so D[0xb7e2d]]
12:19:48  0x7f4a86e893e0 TBufferFile::WriteFastArray(void**, TClass const*, int, bool, TMemberStreamer*) ??:0   + 0xd0 [/cvmfs/atlas.cern.ch/repo/sw/software/21.0/sw/lcg/releases/LCG_88/ROOT/6.08.06/x86_64-slc6-gcc62-opt/lib/libRIO.so D[0xb73e0]]
12:19:48  0x7f4a87016a1a int TStreamerInfo::WriteBufferAux<char**>(TBuffer&, char** const&, TStreamerInfo::TCompInfo* const*, int, int, int, int, int) ??:0   + 0x491a [/cvmfs/atlas.cern.ch/repo/sw/software/21.0/sw/lcg/releases/LCG_88/ROOT/6.08.06/x86_64-slc\
6-gcc62-opt/lib/libRIO.so D[0x244a1a]]
12:19:48  0x7f4a86f0360d TStreamerInfoActions::GenericWriteAction(TBuffer&, void*, TStreamerInfoActions::TConfiguration const*) ??:0   + 0x3d [/cvmfs/atlas.cern.ch/repo/sw/software/21.0/sw/lcg/releases/LCG_88/ROOT/6.08.06/x86_64-slc6-gcc62-opt/lib/libRIO.so\
 D[0x13160d]]
12:19:48  0x7f4a86e88f55 TBufferFile::ApplySequence(TStreamerInfoActions::TActionSequence const&, void*) ??:0   + 0x75 [/cvmfs/atlas.cern.ch/repo/sw/software/21.0/sw/lcg/releases/LCG_88/ROOT/6.08.06/x86_64-slc6-gcc62-opt/lib/libRIO.so D[0xb6f55]]
12:19:48  0x7f4a86e8b49a TBufferFile::WriteClassBuffer(TClass const*, void*) ??:0   + 0xea [/cvmfs/atlas.cern.ch/repo/sw/software/21.0/sw/lcg/releases/LCG_88/ROOT/6.08.06/x86_64-slc6-gcc62-opt/lib/libRIO.so D[0xb949a]]
12:19:49  0x7f4a86e892bc TBufferFile::WriteFastArray(void*, TClass const*, int, TMemberStreamer*) ??:0   + 0x8c [/cvmfs/atlas.cern.ch/repo/sw/software/21.0/sw/lcg/releases/LCG_88/ROOT/6.08.06/x86_64-slc6-gcc62-opt/lib/libRIO.so D[0xb72bc]]
12:19:49  0x7f4a87017688 int TStreamerInfo::WriteBufferAux<char**>(TBuffer&, char** const&, TStreamerInfo::TCompInfo* const*, int, int, int, int, int) ??:0   + 0x5588 [/cvmfs/atlas.cern.ch/repo/sw/software/21.0/sw/lcg/releases/LCG_88/ROOT/6.08.06/x86_64-slc\
6-gcc62-opt/lib/libRIO.so D[0x245688]]
12:19:49  0x7f4a86f1f3b4 TStreamerInfoActions::VectorLooper::GenericWrite(TBuffer&, void*, void const*, TStreamerInfoActions::TLoopConfiguration const*, TStreamerInfoActions::TConfiguration const*) ??:0   + 0x84 [/cvmfs/atlas.cern.ch/repo/sw/software/21.0/s\
w/lcg/releases/LCG_88/ROOT/6.08.06/x86_64-slc6-gcc62-opt/lib/libRIO.so D[0x14d3b4]]

I will try to dig deeper here, thanks for the pointer (no pun intended)!
Cheers,
Al

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.