From cf846b8bfedc1498ef81874e8e0f27a846599399 Mon Sep 17 00:00:00 2001 From: Yura Sokolov Date: Fri, 30 Jun 2023 22:52:10 +0300 Subject: [PATCH] AutoPtr: do 'duplicate' before 'release' Common knowledge in reference counting is "on assignment increment first then decrement", because "just to be deleted" object could hold last reference to "just to be assigned" one. Fixes #3979 --- Foundation/include/Poco/AutoPtr.h | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/Foundation/include/Poco/AutoPtr.h b/Foundation/include/Poco/AutoPtr.h index 8251f46699..27f68a6b61 100644 --- a/Foundation/include/Poco/AutoPtr.h +++ b/Foundation/include/Poco/AutoPtr.h @@ -110,34 +110,23 @@ class AutoPtr { if (_ptr != ptr) { - if (_ptr) _ptr->release(); - _ptr = ptr; - if (shared && _ptr) _ptr->duplicate(); + if (shared && ptr) ptr->duplicate(); + std::swap(_ptr, ptr); + if (ptr) ptr->release(); } return *this; } AutoPtr& assign(const AutoPtr& ptr) { - if (&ptr != this) - { - if (_ptr) _ptr->release(); - _ptr = ptr._ptr; - if (_ptr) _ptr->duplicate(); - } - return *this; + return assign(ptr._ptr, true); } template AutoPtr& assign(const AutoPtr& ptr) { - if (ptr.get() != _ptr) - { - if (_ptr) _ptr->release(); - _ptr = const_cast(ptr.get()); - if (_ptr) _ptr->duplicate(); - } - return *this; + C* nptr = const_cast(ptr.get()); + return assign(nptr, true); } void reset()