-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Valgrind memcheck: still reachable bytes in Singleton #1145
Comments
Yep, the problem is the Does something like: static std::atomic<T*> s_pObject;
T *newObject = m_objectFactory(); // where m_objectFactory is `new T`
s_pObject.store(newObject); But the heap allocated object stored in template<typename T>
struct atomic_unique_ptr {
using pointer = T *;
std::atomic<pointer> ptr;
constexpr atomic_unique_ptr() noexcept : ptr() {}
explicit atomic_unique_ptr(pointer p) noexcept : ptr(p) {}
atomic_unique_ptr(atomic_unique_ptr&& p) noexcept : ptr(p.release()) {}
atomic_unique_ptr& operator=(atomic_unique_ptr&& p) noexcept { reset(p.release()); return *this; }
void reset(pointer p = pointer()) { auto old = ptr.exchange(p); if (old) delete old; }
operator pointer() const { return ptr; }
pointer operator->() const { return ptr; }
pointer get() const { return ptr; }
explicit operator bool() const { return ptr != pointer(); }
pointer release() { return ptr.exchange(pointer()); }
~atomic_unique_ptr() { reset(); }
}; Then replacing the |
On Sun, Oct 15, 2023 at 4:34 AM Dale Weiler ***@***.***> wrote:
Yep, the solution would be to just implement something like
atomic_unique_ptr so that the object returned by m_objectFactory would
also deleted correctly.
template<typename T>struct atomic_unique_ptr {
using pointer = T *;
std::atomic<pointer> ptr;
constexpr atomic_unique_ptr() noexcept : ptr() {}
explicit atomic_unique_ptr(pointer p) noexcept : ptr(p) {}
atomic_unique_ptr(atomic_unique_ptr&& p) noexcept : ptr(p.release()) {}
atomic_unique_ptr& operator=(atomic_unique_ptr&& p) noexcept { reset(p.release()); return *this; }
void reset(pointer p = pointer()) { auto old = ptr.exchange(p); if (old) delete old; }
operator pointer() const { return ptr; }
pointer operator->() const { return ptr; }
pointer get() const { return ptr; }
explicit operator bool() const { return ptr != pointer(); }
pointer release() { return ptr.exchange(pointer()); }
~atomic_unique_ptr() { reset(); }
};
This more or less works as a drop-in replacement and fixes the memory
leaks.
Yeah, the problem is (or has always been) C++03. We still support it. I
know there are folks still using Crypto++ on antique platforms, like
Windows XP and old versions of GCC like 4.4.
To abstract away the differences between auto_ptr (C++03) and unique_ptr
(C++11), the library provided member_ptr<T>. The problem is, it is not
reference counted. There's always a race in destruction in mutithreaded
environments, so the library punted and opted for a memory leak.
For the regularly used stuff, like Integer class, we cutover to a pattern
that avoids the leak (some hand waving):
const Integer& Integer::Two() const {
#if defined CRYPTOPP_CXX11_STATIC_INIT
static const Integer two(2);
return two;
#else
// SIngleton gyrations
#endif
}
If P1363_MGF1 is causing an accumulation of leaks for you, then we can look
at cutting it over to the new pattern.
Jeff
… Message ID: ***@***.***>
|
The new in a Singleton has no complementary delete which causes still reachable bytes in memcheck. (misc.h line 258 and 346)
Code snippet to reproduce (FixedMaxPlaintextLength is the trigger here):
Environment: Ubuntu 20.04, Crypto++ 8.7.0, gcc 11.1.0, Valgrind 3.15.0
Command line:
valgrind --track-origins=yes --leak-check=full --show-leak-kinds=all ..........
Expected output: No leaks at all
Current output:
The text was updated successfully, but these errors were encountered: