Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Copy construction of stateful allocators

35 views
Skip to first unread message

bitrex

unread,
Oct 10, 2017, 1:39:14 PM10/10/17
to
Prior to C+11 I guess it was assumed that allocators were stateless, so
you didn't have to do anything special with their copy constructors (it
seems most were just declared as "throw()."

Now it's possible for allocators to have internal state, but a problem
arises if I write something like the following:

template<typename T>
using RebindAlloc = typename std::allocator_traits
<AllocatorBase<T, StatefulAllocatorPolicy<T>>::template rebind_alloc<T>;

typedef std::basic_string<char, std::char_traits<char>,
RebindAlloc<char>> my_allocated_string_t;

my_allocated_string_t my_string{"abcde"};

If my allocator policy has internal state, say a raw memory block of
some size which is initialized on instantiation with "new" and freed
using "delete []" on a raw pointer stored in a class field in its
destructor, if I just let the policy use the default copy constructor
the allocator is copy constructed in the constructor of
std::basic_string, all the trivially constructable internal fields are
copied over verbatim, and then I get a segmentation fault as the code
tries to delete the same block of memory twice on destruction of both
the original allocator instance and the copy.

So if I want custom allocated container types that use a stateful
allocator to be copy constructible, copy assignable etc. I'd need to
have some kind of shared global state between instances using either a
singleton or reference counting smart pointer to a common structure
holding the mutable fields, I guess?


Daniel

unread,
Oct 10, 2017, 3:04:32 PM10/10/17
to
On Tuesday, October 10, 2017 at 1:39:14 PM UTC-4, bitrex wrote:
>
> If my allocator policy has internal state, say a raw memory block of
> some size which is initialized on instantiation with "new" and freed
> using "delete []" on a raw pointer stored in a class field in its
> destructor, if I just let the policy use the default copy constructor
> the allocator is copy constructed in the constructor of
> std::basic_string, all the trivially constructable internal fields are
> copied over verbatim, and then I get a segmentation fault as the code
> tries to delete the same block of memory twice on destruction of both
> the original allocator instance and the copy.
>
> So if I want custom allocated container types that use a stateful
> allocator to be copy constructible, copy assignable etc. I'd need to
> have some kind of shared global state between instances using either a
> singleton or reference counting smart pointer to a common structure
> holding the mutable fields, I guess?

No, a stateful allocator shouldn't have a default constructor, you should
get (want to get!) compile errors if you attempt to construct an object that
requires a stateful allocator without providing an allocator instance.

Daniel

bitrex

unread,
Oct 11, 2017, 12:23:53 PM10/11/17
to
Ok, but if my policy's specialization default constructor is deleted (or
private) how do I go about actually creating the instance to provide to
the container thru the abstract interface?

Daniel

unread,
Oct 11, 2017, 7:03:13 PM10/11/17
to
On Wednesday, October 11, 2017 at 12:23:53 PM UTC-4, bitrex wrote:
>
> Ok, but if my policy's specialization default constructor is deleted (or
> private) how do I go about actually creating the instance to provide to
> the container thru the abstract interface?

Typically you pass a memory manager to the stateful allocator constructor, see e.g. the boost shared memory allocator examples,

//Initialize the shared memory STL-compatible allocator
ShmemAllocator alloc_inst (segment.get_segment_manager());

https://valelab4.ucsf.edu/svn/3rdpartypublic/boost/doc/html/interprocess/quick_guide.html

It's really important that there is no default constructor, because it's
very easy to make a mistake with instantiating member objects, and you
definitely don't want e.g. ShmemAllocator() to compile.

Daniel

0 new messages