apolukhin / Boost.DLL

Library for comfortable work with DLL and DSO
https://boost.org/libs/dll
109 stars 69 forks source link

Memory leak in example code #26

Closed rettichschnidi closed 8 years ago

rettichschnidi commented 8 years ago

To my understanding, the usage of the aliasing constructor in example8 induces a memory leak as the my_refcounting_api pointer plugin does not get freed by this kind of shared_ptr:

8) The aliasing constructor: constructs a shared_ptr which shares ownership information with r, but holds an unrelated and unmanaged pointer ptr. Even if this shared_ptr is the last of the group to go out of scope, it will call the destructor for the object originally managed by r. However, calling get() on this will always return a copy of ptr. It is the responsibility of the programmer to make sure that this ptr remains valid as long as this shared_ptr exists, such as in the typical use cases where ptr is a member of the object managed by r or is an alias (e.g., downcast) of r.get()

How about some auxiliary wrapper:

template <typename T> struct ResourceWrapper {
  boost::dll::shared_library m_Dll;
  std::unique_ptr<T> m_T;
  ResourceWrapper(boost::dll::shared_library &dllLib, std::unique_ptr<T> i)
      : m_Dll(dllLib), m_T(std::move(i)) {}
};

Then use it along those lines:

boost::dll::shared_library myLib("myLib.so");
auto myObject = std::make_unique<MyType>();
auto myWrapper = std::make_shared<ResourceWrapper<MyType>>(myLib, std::move(myObject));
auto myAliasedSharedPointer = std::shared_ptr<MyType>(myWrapper, myWrapper->m_T.get());

I am not sure if this really THE way to go. But according to my understanding, this at least does not leak memory.

apolukhin commented 8 years ago

Thanks a lot for the error report and analysis!

Fixed in 2a09a92, polished in 73e4445.