diff --git a/tree/ntuple/src/RFieldSequenceContainer.cxx b/tree/ntuple/src/RFieldSequenceContainer.cxx index 0917432397507..7fcef29575a64 100644 --- a/tree/ntuple/src/RFieldSequenceContainer.cxx +++ b/tree/ntuple/src/RFieldSequenceContainer.cxx @@ -264,10 +264,7 @@ unsigned char *ROOT::RRVecField::ResizeRVec(void *rvec, std::size_t nItems, std: } // TODO Increment capacity by a factor rather than just enough to fit the elements. - if (owns) { - // *beginPtr points to the array of item values (allocated in an earlier call by the following malloc()) - free(*beginPtr); - } + Internal::DestroyRVecWithChecks(itemField->GetAlignment(), beginPtr, capacityPtr); // We trust that malloc returns a buffer with large enough alignment. // This might not be the case if T in RVec is over-aligned. *beginPtr = static_cast(malloc(nItems * itemSize)); diff --git a/tree/ntuple/test/rfield_vector.cxx b/tree/ntuple/test/rfield_vector.cxx index 0e505cbd7e5ad..dbf4526fc0133 100644 --- a/tree/ntuple/test/rfield_vector.cxx +++ b/tree/ntuple/test/rfield_vector.cxx @@ -203,6 +203,39 @@ TEST(RNTuple, RVec) EXPECT_EQ(1.0, (*rdJetsAsStdVector)[0]); } +TEST(RNTuple, RVecResizeSmall) +{ + FileRaii fileGuard("test_ntuple_rvec_small.root"); + + constexpr int N = 260; // more elements than fit in any small vector storage + + { + auto model = RNTupleModel::Create(); + auto v = model->MakeField>("v"); + for (int i = 0; i < N; ++i) { + v->push_back(i); + } + + auto writer = RNTupleWriter::Recreate(std::move(model), "ntpl", fileGuard.GetPath()); + writer->Fill(); + } + + auto reader = RNTupleReader::Open("ntpl", fileGuard.GetPath()); + EXPECT_EQ(1U, reader->GetNEntries()); + + ROOT::RVec v; + EXPECT_TRUE(ROOT::Detail::VecOps::IsSmall(v)); + auto e = reader->CreateEntry(); + e->BindRawPtr("v", &v); + + reader->LoadEntry(0, *e); + ASSERT_EQ(v.size(), N); + EXPECT_FALSE(ROOT::Detail::VecOps::IsSmall(v)); + for (int i = 0; i < N; ++i) { + EXPECT_EQ(i, v[i]); + } +} + TEST(RNTuple, RVecTypeErased) { FileRaii fileGuard("test_ntuple_rvec_typeerased.root");