From 904075e1f19bfeece987698885d1008f85491697 Mon Sep 17 00:00:00 2001 From: Sokolov Yura Date: Thu, 23 Nov 2023 06:49:10 +0300 Subject: [PATCH] AutoPtr: do 'duplicate' before 'release' (#4068) 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 8251f4669..27f68a6b6 100644 --- a/Foundation/include/Poco/AutoPtr.h +++ b/Foundation/include/Poco/AutoPtr.h @@ -110,34 +110,23 @@ public: { 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()