[libcxx-dev] Possible bug in std::allocate_shared implementation

Laurent Pinchart via libcxx-dev libcxx-dev at lists.llvm.org
Mon Apr 29 02:28:01 PDT 2019


Hello,

I ran into what I believe can be a bug in the libc++ implementation of
std::allocate_shared<>. The following code fails to compile due to two
issues.

------------------------------------------------------------------------
#include <memory>

class Private;

class Factory {
public:
	static std::shared_ptr<Private> allocate();
};

class Private {
private:
	friend class Factory;
	Private() { }
	~Private() { }
};

std::shared_ptr<Private> Factory::allocate()
{
	struct Allocator : std::allocator<Private> {
		void construct(void *p)
		{
			::new(p) Private();
		}
		void destroy(Private *p)
		{
			p->~Private();
		}
	};

	return std::allocate_shared<Private>(Allocator());
}
------------------------------------------------------------------------

First of all, commit 7700912976a5 ("Land D28253 which fixes PR28929
(which we mistakenly marked as fixed before)") introduced a static
assert to verify that the object type is constructible:

static_assert( is_constructible<_Tp, _Args...>::value, "Can't construct object in allocate_shared" );

This fails, as Private is not constructible in the context of the
std::allocate_shared<> implementations, due to its private constructor
and destructor. I believe that the check is incorrect, as I don't see
anything in the C++ standard that mandates the object type to be
constructible by std::allocate_shared<> itself.

I tried removing the static asserts, and that's where the real fun
began. If my understanding is correct, in order to store the pointed
data, libc++ uses an internal __shared_ptr_emplace<_Tp, _Alloc> class
that contains (through a few levels of inheritance) an instance of _Tp.
That class has its destructor implicitly deleted due to the private
nature of ~Private(). The compiler then complains about

/usr/include/c++/v1/memory:3604:7: error: deleted function '~__shared_ptr_emplace' cannot override a non-deleted function
class __shared_ptr_emplace
[...]
/usr/include/c++/v1/memory:3513:13: note: overridden virtual function is here
    virtual ~__shared_weak_count();

My limited knowledge of libc++ internals and of C++ compilers in general
prevents me from proposing a fix. I would appreciate if someone could
first confirm that the test case is valid, and then hopefully help :-)

-- 
Regards,

Laurent Pinchart


More information about the libcxx-dev mailing list