From 39f2527012034f9df9a1ed9e618d256651a5974e Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Sun, 23 Oct 2016 10:41:26 +0300 Subject: [PATCH] Fixed memory leak [#METR-2944]. --- .../include/ext/shared_ptr_helper.hpp | 45 +++++++++++++------ 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/libs/libcommon/include/ext/shared_ptr_helper.hpp b/libs/libcommon/include/ext/shared_ptr_helper.hpp index cedfc6dec98..e18a0ee8818 100644 --- a/libs/libcommon/include/ext/shared_ptr_helper.hpp +++ b/libs/libcommon/include/ext/shared_ptr_helper.hpp @@ -5,36 +5,55 @@ namespace ext { -/** - * Class AllocateShared allow to make std::shared_ptr from T with private constructor. - * Derive your T class from shared_ptr_helper, define him as friend and call allocate_shared()/make_shared() method. -**/ -template +/** Class AllocateShared allow to make std::shared_ptr from T with private constructor. + * Derive your T class from shared_ptr_helper, define him as friend and call allocate_shared()/make_shared() method. + */ +template class shared_ptr_helper { protected: typedef typename std::remove_const::type TNoConst; - template + template struct Deleter { void operator()(typename TAlloc::value_type * ptr) { - std::allocator_traits::destroy(alloc, ptr); + using AllocTraits = std::allocator_traits; + ptr->~TNoConst(); + AllocTraits::deallocate(alloc, ptr, 1); } + TAlloc alloc; }; - ///see std::allocate_shared - template - static std::shared_ptr allocate_shared(const TAlloc & alloc, TArgs && ... args) + /// see std::allocate_shared + template + static std::shared_ptr allocate_shared(const TAlloc & alloc, TArgs &&... args) { + using AllocTraits = std::allocator_traits; TAlloc alloc_copy(alloc); - return std::shared_ptr(new (std::allocator_traits::allocate(alloc_copy, 1)) TNoConst(std::forward(args)...), Deleter(), alloc_copy); + + auto ptr = AllocTraits::allocate(alloc_copy, 1); + + try + { + new (ptr) TNoConst(std::forward(args)...); + } + catch (...) + { + AllocTraits::deallocate(alloc_copy, ptr, 1); + throw; + } + + return std::shared_ptr( + ptr, + Deleter(), + alloc_copy); } - template - static std::shared_ptr make_shared(TArgs && ... args) + template + static std::shared_ptr make_shared(TArgs &&... args) { return allocate_shared(std::allocator(), std::forward(args)...); }