Custom allocator sample code for vector

A

Alex Vinokur

I am looking for any custom allocator sample code for std::vector.

Thanks.
 
S

Sharad Kala

When should 'construct' and 'destroy' be invoked?

An allocator has to provide a construct and destruct operation. You may want
to take a look at 20.1.5 (Allocator requirements).

Construct is used to initialize the memory allocated with a value. This is
basically a call to placement new. So basically construct is invoked when an
object is created in the container.
Destroy simply calls the destructor for the object.

-Sharad
 
A

Alex Vinokur

Sharad Kala said:
An allocator has to provide a construct and destruct operation. You may want
to take a look at 20.1.5 (Allocator requirements).

Construct is used to initialize the memory allocated with a value. This is
basically a call to placement new. So basically construct is invoked when an
object is created in the container.

For instance, v.push_back (element) for vector?

However, in http://www.josuttis.com/libbook/memory/myalloc1.cpp.html construct isn't invoked while push_back invocation.
 
A

Alex Vinokur

Alex Vinokur said:
For instance, v.push_back (element) for vector?

However, in http://www.josuttis.com/libbook/memory/myalloc1.cpp.html construct isn't invoked while push_back invocation.

[snip]


Compiler g++ 3.3.1 (cygming special).
Here is a fragment from file stl_alloc.h.

/**
* @defgroup Allocators Memory Allocators
* @if maint
* stl_alloc.h implements some node allocators. These are NOT the same as
* allocators in the C++ standard, nor in the original H-P STL. They do not
* encapsulate different pointer types; we assume that there is only one
* pointer type. The C++ standard allocators are intended to allocate
* individual objects, not pools or arenas.
*
* In this file allocators are of two different styles: "standard" and
* "SGI" (quotes included). "Standard" allocators conform to 20.4. "SGI"
* allocators differ in AT LEAST the following ways (add to this list as you
* discover them):
*
* - "Standard" allocate() takes two parameters (n_count,hint=0) but "SGI"
* allocate() takes one paramter (n_size).
* - Likewise, "standard" deallocate()'s argument is a count, but in "SGI"
* is a byte size.
* - max_size(), construct(), and destroy() are missing in "SGI" allocators.
* - reallocate(p,oldsz,newsz) is added in "SGI", and behaves as
* if p=realloc(p,newsz).
*
* "SGI" allocators may be wrapped in __allocator to convert the interface
* into a "standard" one.
* @endif
*
* @note The @c reallocate member functions have been deprecated for 3.2
* and will be removed in 3.4. You must define @c _GLIBCPP_DEPRECATED
* to make this visible in 3.2; see c++config.h.
*
* The canonical description of these classes is in docs/html/ext/howto.html
* or online at http://gcc.gnu.org/onlinedocs/libstdc++/ext/howto.html#3
*/

Perhaps, MyAlloc in the Josuttis' sample works as "SGI" allocator which doesn't contain construct(), and destroy() (?).
 
A

Alex Vinokur

Sharad Kala said:
construct isn't invoked while push_back invocation.

Try putting a breakpoint in Construct and then see.

I put assert(0) in construct().
No response.

// initialize elements of allocated storage p with value value
void construct (pointer p, const T& value)
{
// initialize memory with placement new
new((void*)p)T(value);
assert (0); // Added by me
}

[snip]
 
S

Sharad Kala

I put assert(0) in construct().
No response.

Is NDEBUG macro defined ? I can very much see the assert failure on MS VC 7
if I insert the above line (in debug build). Try putting cout << "In
construct" and then see.
 
A

Alex Vinokur

Sharad Kala said:
Is NDEBUG macro defined ? I can very much see the assert failure on MS VC 7
if I insert the above line (in debug build). Try putting cout << "In
construct" and then see.

Done: cout << "In construct" has been put.
No response too.
It seems that construct() is not invoked.
 
A

Alex Vinokur

Alex Vinokur said:
Sharad Kala said:
construct isn't invoked while push_back invocation.

Try putting a breakpoint in Construct and then see.

I put assert(0) in construct().
No response.

// initialize elements of allocated storage p with value value
void construct (pointer p, const T& value)
{
// initialize memory with placement new
new((void*)p)T(value);
assert (0); // Added by me
}

[snip]
[snip]

Different compilers produce quite different behavior with the same custom allocator.

Here is the Nicolai M. Josuttis' code sample with cosmetic changes added by me to profile the executable:
http://groups.google.com/[email protected]

Here are log files for the following compilers
* GNU g++ : http://groups.google.com/[email protected]
* Microsoft C++ : http://groups.google.com/[email protected]
* Borland C++ : http://groups.google.com/[email protected]

We can see that
* GNU g++ 3.3.1 doesn't invoke construct() and destroy();
* Microsoft C++ 13.00 and Borland C++ 5.5.1 do invoke construct() and destroy();

We can see also that behavior Microsoft C++ 13.00 and Borland C++ 5.5.1 is quite different;
for instance, Borland C++ allocates memory for 256 elements, Microsoft C++ allocates memory for small number of elements.


So, behavior of a custom allocator is significantly compiler-dependent.
The question is what can one achieve using a _custom_ allocator?

The more specific question: do we need construct() and destroy() indeed? For instance, g++ doesn't use them.
 
T

tom_usenet

Thanks.

In that sample we can see that methods 'allocate' and 'deallocate' were invoked.
But methods 'construct' and 'destroy' were not invoked.
When should 'construct' and 'destroy' be invoked?

They may never be invoked - containers are not required to call them.
I believe that Dinkumware's lib does call them, since they support
"unusual" pointer types and memory models. I doubt anyone else does.

Tom
 
S

Sharad Kala

They may never be invoked - containers are not required to call them.
I believe that Dinkumware's lib does call them, since they support
"unusual" pointer types and memory models. I doubt anyone else does.

Why are they then as part of standard in allocator requirements in 20.1.5 ?
Is it an optional feature or are the compilers not being conformant ?
 
T

tom_usenet

Why are they then as part of standard in allocator requirements in 20.1.5 ?

I think the original intention was that they were there to allow
pointer types that aren't T*. However, the standard says for
construct:

Effect: new ((void*)p) T(t)

I think that is a defect, since it requires that
allocator::pointer_type be castable to void*, which is not a good
requirement to have!
Is it an optional feature or are the compilers not being conformant ?

It's an optional feature whether or not the containers use it or not -
I don't see any mention of whether containers must call it or not,
which I think makes it optional.

Tom
 
J

jose luis fernandez diaz

Alex Vinokur said:
Thanks.

In that sample we can see that methods 'allocate' and 'deallocate' were invoked.
But methods 'construct' and 'destroy' were not invoked.
When should 'construct' and 'destroy' be invoked?

'allocate'only reserves raw memory. Wnen you insert objects in that
allocated memory, for example with vector 'push_back' method,
'construct' method must be invoked. It is invoked from vector
'push_back' method. Can you post vector 'push_back' method code from
the vector library file that you are using ?

Regards,
Jose Luis.
 
A

Alex Vinokur

jose luis fernandez diaz said:
'allocate'only reserves raw memory. Wnen you insert objects in that
allocated memory, for example with vector 'push_back' method,
'construct' method must be invoked. It is invoked from vector
'push_back' method. Can you post vector 'push_back' method code from
the vector library file that you are using ?
[snip]

--------------------------------------------
GNU g++ version 3.3.1 (cygming special).
GNU Standard C++ Library libstdc++-v3
--------------------------------------------

Here is the push_back() method from file stl_vector.h
http://www.mit.edu/afs/athena/astaff/project/gccdev/egcs/libstdc++-v3/include/bits/stl_vector.h


--------- push_back() : BEGIN ---------
// [23.2.4.3] modifiers
/**
* @brief Add data to the end of the %vector.
* @param x Data to be added.
*
* This is a typical stack operation. The function creates an element at
* the end of the %vector and assigns the given data to it.
* Due to the nature of a %vector this operation can be done in constant
* time if the %vector has preallocated space available.
*/
void
push_back(const value_type& __x)
{
if (_M_finish != _M_end_of_storage)
{
_Construct(_M_finish, __x);
++_M_finish;
}
else
_M_insert_aux(end(), __x);
}
--------- push_back() : END -----------
 
A

Alex Vinokur

Alex Vinokur said:
[snip]
Here is the Nicolai M. Josuttis' code sample with cosmetic changes added by me to profile the executable:
http://groups.google.com/[email protected]

Here are log files for the following compilers
* GNU g++ : http://groups.google.com/[email protected] [snip]

We can see that
* GNU g++ 3.3.1 doesn't invoke construct() and destroy(); [snip]


Hi everybody !

There's a behaviour in STL allocator I don't understand, I hope
somebody can
help me...

I'm trying to customize an allocator to track the insertion/deletion
of objects
in a container,
decorating the standard allocator functions construct() and destroy().

The problem is that it seems that those functions are never called in
STL
containers, instead
a global template function _Construct() (defined in <stl_construct.h>)
is
called, that is
completely unaware of allocators.

This is a bug.
[snip]

See also several relevant threads from news://news.gmane.org/gmane.comp.gcc.libstdc++.devel

The thread titled "Custom allocator for vector and libstdc++-v3"
http://thread.gmane.org/gmane.comp.gcc.libstdc++.devel/10087

The thread titled "allocator construct() / destruct() behaviour..."
http://thread.gmane.org/gmane.comp.gcc.libstdc++.devel/9814

The thread titled "PATCH: use construct and destroy from user-provided allocators"
http://thread.gmane.org/gmane.comp.gcc.libstdc++.devel/9847
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,009
Latest member
GidgetGamb

Latest Threads

Top