Skip to content

Commit fd5dd4d

Browse files
committed
[ntuple] Implement RField<TObject>::ReadInClusterImpl
Otherwise RFieldBase::ReadInClusterImpl tries to use the principal column to translate to a global index, which results in a nullptr dereference. Fixes #18404
1 parent 618bd67 commit fd5dd4d

File tree

3 files changed

+48
-0
lines changed

3 files changed

+48
-0
lines changed

Diff for: tree/ntuple/v7/inc/ROOT/RField.hxx

+1
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,7 @@ protected:
475475
std::size_t AppendImpl(const void *from) final;
476476
void ReadTObject(void *to, UInt_t uniqueID, UInt_t bits);
477477
void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final;
478+
void ReadInClusterImpl(RNTupleLocalIndex localIndex, void *to) final;
478479

479480
void AfterConnectPageSource() final;
480481

Diff for: tree/ntuple/v7/src/RFieldMeta.cxx

+8
Original file line numberDiff line numberDiff line change
@@ -995,6 +995,14 @@ void ROOT::RField<TObject>::ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void
995995
ReadTObject(to, uniqueID, bits);
996996
}
997997

998+
void ROOT::RField<TObject>::ReadInClusterImpl(RNTupleLocalIndex localIndex, void *to)
999+
{
1000+
UInt_t uniqueID, bits;
1001+
CallReadOn(*fSubfields[0], localIndex, &uniqueID);
1002+
CallReadOn(*fSubfields[1], localIndex, &bits);
1003+
ReadTObject(to, uniqueID, bits);
1004+
}
1005+
9981006
void ROOT::RField<TObject>::AfterConnectPageSource()
9991007
{
10001008
if (GetOnDiskTypeVersion() != 1) {

Diff for: tree/ntuple/v7/test/rfield_vector.cxx

+39
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#include "ntuple_test.hxx"
22

3+
#include <TObject.h>
4+
35
// A layer of indirection to hide std::vector's second template parameter.
46
// This way we can generalize tests over RVec and std::vector using a template template parameter (see below).
57
template <typename T>
@@ -494,3 +496,40 @@ TEST(RNTuple, VectorOfBitset)
494496
EXPECT_EQ("111", ptrVecOfBitset->at(0).to_string());
495497
EXPECT_EQ("000", ptrVecOfBitset->at(1).to_string());
496498
}
499+
500+
TEST(RNTuple, VectorOfTObject)
501+
{
502+
FileRaii fileGuard("test_ntuple_vector_of_tobject.root");
503+
{
504+
auto model = RNTupleModel::Create();
505+
auto objs = model->MakeField<std::vector<TObject>>("objs");
506+
auto writer = RNTupleWriter::Recreate(std::move(model), "ntpl", fileGuard.GetPath());
507+
508+
TObject obj;
509+
obj.SetUniqueID(42);
510+
objs->push_back(obj);
511+
obj.SetUniqueID(43);
512+
objs->push_back(obj);
513+
writer->Fill();
514+
writer->CommitCluster();
515+
516+
objs->clear();
517+
obj.SetUniqueID(44);
518+
objs->push_back(obj);
519+
writer->Fill();
520+
}
521+
522+
auto reader = RNTupleReader::Open("ntpl", fileGuard.GetPath());
523+
ASSERT_EQ(2u, reader->GetNEntries());
524+
auto &entry = reader->GetModel().GetDefaultEntry();
525+
auto objs = entry.GetPtr<std::vector<TObject>>("objs");
526+
527+
reader->LoadEntry(0);
528+
ASSERT_EQ(2u, objs->size());
529+
EXPECT_EQ(42u, objs->at(0).GetUniqueID());
530+
EXPECT_EQ(43u, objs->at(1).GetUniqueID());
531+
532+
reader->LoadEntry(1);
533+
ASSERT_EQ(1u, objs->size());
534+
EXPECT_EQ(44u, objs->at(0).GetUniqueID());
535+
}

0 commit comments

Comments
 (0)