Re: Placement new[]
Le 30/01/2014 09:38, Wouter van Ooijen a ?crit :
Joe The Smoe schreef op 30-Jan-14 9:18 AM:
The problem I meet is that I have something working pretty well except
for the placement new[] which places the first element of the array 4
bytes after the address returned by the new[] operator.
Ordinary new and delete deal with a pointer to a fixed type, hence known
size of the object (the compiler can supply the size to the delete call).
Not so for the delete[] operator: it gets a pointer to the first entry,
but there can be just that one entry, but it could equally be a
1000-entry array. There is no guaranteed way for the compiler to known
this at the delete. Hence a common implementation of new[] puts the size
in front of the allocated block of memory, so delete[] can find it and
knows the size of the block.
OK, I understand.
So, my implementation of the class pool is probably wrong. I intended to
put a pointer to the allocating pool object just before the allocated
block asked by a placement new/new[] in order to allow only code
modification by replacing the new operator by a it placement's
counterpart, keeping the delete invocation equal:
// adding a thread local pool object
pool p();
// using placement new in place of usual new operator
toto *ptr = new (p) toto(3);
... (doing something with ptr)
// but object get deleted normally (which that's the point is
// not the common way of doing, I admit...)
delete ptr;
where the delete operator for the class toto is taken from its parent
class "on_pool" --- thanks for the hint :) :
class on_pool
{
public:
// get_pool() returns the address of the allocating pool
// for "this" by fetching the field placed before
// the object's address: "this - sizeof(pool *)" bytes
pool & get_pool() const
{ return **((pool **)(pool::shift_left((void *)this))); };
// as expected the placement new operator
void *operator new(size_t n_byte, pool & p)
{ return p.alloc(n_byte); };
// and its associated "on-exception" delete operator
void operator delete(void *ptr, pool & p)
{ p.dealloc(ptr); };
// the delete operator overwritten to release address
// for the associated pool
void operator delete(void *ptr)
{ ((on_pool *)ptr)->get_pool().dealloc(ptr); };
// this works fine, but doing the same for placement new[]
// and the on_pool::delete[] operators fails because
// delete[] should not be used against object allocated
// by a placement new[] ... I'm hitting compiler internal's
// implementation of new[] and delete[] default operators.
};
class toto: public on_pool
{
...
};
Sight ... :-(
I wished I could abstract well the use of placement new in the current
code, but it seems I cannot avoid directly calling the destructor and
then the delete[] operator. Which to my humble point of view brings a
big difference about the readability of the code and which is source of
error (delete without prior desctructor call, and viceversa),
All the block recycling is done by the pool class not
by the caller (allocation/release abstraction) but I cannot abstract for
the caller the fact that the memory is allocated on the pool by just the
slightly modifying the "new" invocation...
*Sight*
P.S: the placement new, new[], delete, and delete[] operators are
textually identical for each class, I can use a #define macro to add
them to each class. But, is there a better C++ way of doing that?
Inherit from a base class?
Yes, I stupidly thought the new and delete operator where not
inheritable... Just tested it and it perfectly works! Thanks. :)