From c104214f74bd4753068ebbc3d8853c149dc984e9 Mon Sep 17 00:00:00 2001
From: Mark Olesen <Mark.Olesen@esi-group.com>
Date: Tue, 9 Oct 2018 08:27:50 +0200
Subject: [PATCH] ENH: avoid change when setting UPtrList twice (issue #1035)

    UPtrList::set(const label i, T* ptr);

No-op if the new pointer value is identical to the current content.
This avoid memory management issues.
---
 applications/test/PtrList/Test-PtrList.C              | 11 +++++++++++
 src/OpenFOAM/containers/PtrLists/PtrList/PtrList.H    |  1 +
 src/OpenFOAM/containers/PtrLists/UPtrList/UPtrList.H  |  2 +-
 src/OpenFOAM/containers/PtrLists/UPtrList/UPtrListI.H |  4 ++++
 4 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/applications/test/PtrList/Test-PtrList.C b/applications/test/PtrList/Test-PtrList.C
index e76ee21e09..70e8ce184c 100644
--- a/applications/test/PtrList/Test-PtrList.C
+++ b/applications/test/PtrList/Test-PtrList.C
@@ -328,6 +328,17 @@ int main(int argc, char *argv[])
             <<"addresses:" << nl;
         printAddr(Info, list1);
         printAddr(Info, list1a);
+        Info<<"values:" << nl;
+        print(Info, list1a);
+
+        // This should not cause problems (ie, no deletion)
+        {
+            auto* ptr = &(list1a.first());
+            list1a.set(0, ptr);
+            Info<<"values:" << nl;
+            print(Info, list1a);
+        }
+
 
         PtrList<Scalar> list1b(list1a, true);
 
diff --git a/src/OpenFOAM/containers/PtrLists/PtrList/PtrList.H b/src/OpenFOAM/containers/PtrLists/PtrList/PtrList.H
index 291fc65ff3..d1296de3f2 100644
--- a/src/OpenFOAM/containers/PtrLists/PtrList/PtrList.H
+++ b/src/OpenFOAM/containers/PtrLists/PtrList/PtrList.H
@@ -154,6 +154,7 @@ public:
         inline bool set(const label i) const;
 
         //- Set element to given pointer and return old element (can be null)
+        //  No-op if the new pointer value is identical to the current content.
         inline autoPtr<T> set(label i, T* ptr);
 
         //- Set element to given autoPtr and return old element
diff --git a/src/OpenFOAM/containers/PtrLists/UPtrList/UPtrList.H b/src/OpenFOAM/containers/PtrLists/UPtrList/UPtrList.H
index f778c850f9..99664df337 100644
--- a/src/OpenFOAM/containers/PtrLists/UPtrList/UPtrList.H
+++ b/src/OpenFOAM/containers/PtrLists/UPtrList/UPtrList.H
@@ -182,7 +182,7 @@ public:
 
         //- Set element to specified pointer and return the old list element,
         //- which can be a nullptr.
-        //  No checks on new element
+        //  No-op if the new pointer value is identical to the current content.
         inline T* set(const label i, T* ptr);
 
         //- Reorder elements. Reordering must be unique (ie, shuffle).
diff --git a/src/OpenFOAM/containers/PtrLists/UPtrList/UPtrListI.H b/src/OpenFOAM/containers/PtrLists/UPtrList/UPtrListI.H
index d416564a3b..6045c8ab3b 100644
--- a/src/OpenFOAM/containers/PtrLists/UPtrList/UPtrListI.H
+++ b/src/OpenFOAM/containers/PtrLists/UPtrList/UPtrListI.H
@@ -180,6 +180,10 @@ template<class T>
 inline T* Foam::UPtrList<T>::set(const label i, T* ptr)
 {
     T* old = ptrs_[i];
+    if (old == ptr)
+    {
+        return nullptr;  // Content did not change
+    }
     ptrs_[i] = ptr;
     return old;
 }
-- 
GitLab