Skip to content

Commit 45b2c98

Browse files
committed
[Minuit2] Rule of five for Minuit2 linear algebra classes
Avoid potential double free that would happen if the LASymMatrix or LAVector is move-constructed. The subsequent undefined behavior might be resulting in the sporadic build failures that we currently have.
1 parent d903772 commit 45b2c98

File tree

1 file changed

+36
-0
lines changed

1 file changed

+36
-0
lines changed

math/minuit2/inc/Minuit2/MnMatrix.h

+36
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,15 @@ class LASymMatrix {
464464
std::memcpy(fData, v.Data(), fSize * sizeof(double));
465465
}
466466

467+
LASymMatrix(LASymMatrix &&v)
468+
: fSize(v.size()),
469+
fNRow(v.Nrow()),
470+
fData(v.fData)
471+
{
472+
v.fData = nullptr;
473+
}
474+
475+
467476
LASymMatrix &operator=(const LASymMatrix &v)
468477
{
469478
if (fSize < v.size()) {
@@ -472,11 +481,22 @@ class LASymMatrix {
472481
fSize = v.size();
473482
fNRow = v.Nrow();
474483
fData = (double *)StackAllocatorHolder::Get().Allocate(sizeof(double) * fSize);
484+
} else if (fSize > v.size()) {
485+
throw std::runtime_error("Can't assign smaller LASymMatrix to larger LASymMatrix");
475486
}
476487
std::memcpy(fData, v.Data(), fSize * sizeof(double));
477488
return *this;
478489
}
479490

491+
LASymMatrix &operator=(LASymMatrix &&v)
492+
{
493+
fSize = v.size();
494+
fNRow = v.Nrow();
495+
fData = v.Data();
496+
v.fData = nullptr;
497+
return *this;
498+
}
499+
480500
template <class T>
481501
LASymMatrix(const ABObj<sym, LASymMatrix, T> &v)
482502
: fSize(v.Obj().size()),
@@ -822,6 +842,12 @@ class LAVector {
822842
StackAllocatorHolder::Get().Deallocate(fData);
823843
}
824844

845+
LAVector(LAVector &&v)
846+
: fSize(v.size()), fData(v.Data())
847+
{
848+
fData = nullptr;
849+
}
850+
825851
LAVector(const LAVector &v) : LAVector{std::span<const double>{v.Data(), v.size()}} {}
826852

827853
explicit LAVector(std::span<const double> v)
@@ -838,11 +864,21 @@ class LAVector {
838864
StackAllocatorHolder::Get().Deallocate(fData);
839865
fSize = v.size();
840866
fData = (double *)StackAllocatorHolder::Get().Allocate(sizeof(double) * fSize);
867+
} else if (fSize > v.size()) {
868+
throw std::runtime_error("Can't assign smaller LAVector to larger LAVector");
841869
}
842870
std::memcpy(fData, v.Data(), fSize * sizeof(double));
843871
return *this;
844872
}
845873

874+
LAVector &operator=(LAVector &&v)
875+
{
876+
fSize = v.fSize;
877+
fData = v.fData;
878+
v.fData = nullptr;
879+
return *this;
880+
}
881+
846882
template <class T>
847883
LAVector(const ABObj<vec, LAVector, T> &v)
848884
: fSize(v.Obj().size()), fData((double *)StackAllocatorHolder::Get().Allocate(sizeof(double) * v.Obj().size()))

0 commit comments

Comments
 (0)