Replacing new and delete operations

J

Jay Nabonne

Hi,

This might sound odd, but we want to replace the allocation scheme used by
new and delete without changing operator new and operator delete. (The
global operators are shared and we can't change them.)

We can replace operator new functionality by providing additional
parameters to the new function call (ala Stroustrup):

class foo_t;
extern foo_t foo;
void * operator new(size_t size, const foo_t&) { return malloc(size); }
void operator delete(void * p, const foo_t&) { free(p); }

char* p = new(foo) char;

But you can't do that with operator delete. There's no way to invoke the
parametrized delete operator, short of calling "operator delete(p, foo)"
which won't invoke destructors (it just calls the memory deallocator).

So, is there a way to replace delete functionality without overriding the
global delete operator?

- Jay
 
S

shez

Jay said:
class foo_t;
extern foo_t foo;
void * operator new(size_t size, const foo_t&) { return malloc(size); }
void operator delete(void * p, const foo_t&) { free(p); }

char* p = new(foo) char;

But you can't do that with operator delete. There's no way to invoke the
parametrized delete operator, short of calling "operator delete(p, foo)"
which won't invoke destructors (it just calls the memory
deallocator).

you can write a template function inside your memory deallocator:

template <class T>
void destructAndDeallocate(T* p)
{
p->~T();
free(p);
}

So you can use it like this:

SomeObject *x = new (foo) SomeObject(...);
....
foo.destructAndDeallocate(x);

-shez-
 
D

Dietmar Kuehl

Jay said:
We can replace operator new functionality by providing additional
parameters to the new function call (ala Stroustrup):

class foo_t;
extern foo_t foo;
void * operator new(size_t size, const foo_t&) { return malloc(size); }
void operator delete(void * p, const foo_t&) { free(p); }

char* p = new(foo) char;

Note that a thus constructed object needs to be explicitly
destructed before calling 'operator delete()' with the corresponding
pionter:

| p->~char();
| operator delete(p, foo);
But you can't do that with operator delete. There's no way to invoke the
parametrized delete operator, short of calling "operator delete(p, foo)"
which won't invoke destructors (it just calls the memory
deallocator).

Right, there is no syntax which both destructs the object
and calls 'operator delete()'. You need to do a two step
process if you use a placement form of "new" (unless you
use a 'std::nothrow' version of "new" in which case you can
simply "delete" the object).
 
J

Jay Nabonne

Note that a thus constructed object needs to be explicitly
destructed before calling 'operator delete()' with the corresponding
pionter:

| p->~char();
| operator delete(p, foo);

Right, there is no syntax which both destructs the object
and calls 'operator delete()'. You need to do a two step
process if you use a placement form of "new" (unless you
use a 'std::nothrow' version of "new" in which case you can
simply "delete" the object).

This isn't the placement form of new (AFAICT). This is calling new with
different parameters ala "nothrow".

(See for example, "19.4.5 Dynamic Memory" in The C++ Programming Language,
Special Edition).

I have a feeling the answer to my question is "no", but I wanted to give
the gurus a chance at it before I give up.

- Jay
 
J

Jay Nabonne

Jay Nabonne wrote:
So you can use it like this:

SomeObject *x = new (foo) SomeObject(...);
...
foo.destructAndDeallocate(x);

We could do that. The ultimate goal was to use macros to allow the normal
usage of new and delete:

#define new new(foo)
#define delete ...???

But this two-step method would work if we don't need that restriction.

Thanks!

- Jay
 
D

Dietmar Kuehl

This isn't the placement form of new (AFAICT). This is calling new with
different parameters ala "nothrow".

5.3.4 (expr.new) paragraph 11 at least calls this form of new expression
"placement syntax of new". Anyway, according to 18.4.1.1
(lib.new.delete.single) paragraph 12 'operator delete(void*)' only accepts
pointers obtained from 'operator new(std::size_t)'. However, according to
5.3.5 (expr.delete) paragraph 7, a delete expression calls a deallocation
function and the only real operation in this context is
'operator delete(void*)'. This is where things get fuzzy: I can't find a
quote where this is indeed the only option although I'm pretty sure it is.

This effectively means, you cannot use delete expressions on pointers
obtained using the placement syntax of new, i.e. when passing additional
parameters to 'operator new()' during construction. This effectively
implies that you need to explicitly destroy the object and cope with
memory release in a second step.
(See for example, "19.4.5 Dynamic Memory" in The C++ Programming Language,
Special Edition).

I don't have TC++PL3 accessible right now but I know what you are talking
of anyway :)
I have a feeling the answer to my question is "no", but I wanted to give
the gurus a chance at it before I give up.

Well, the answer is "yes", there is a way: you could use a function
template which first destroys the object and then releases the memory,
e.g.

template <typename T>
void my_delete(T* ptr) {
{
ptr->~T(); // destroy the object
release(ptr);
}

If your deallocation function (above called 'release()') needs extra
parameters, you need to obtain them somehow from the pointer, e.g. by
associating them with pointer using e.g. an 'std::map<void*, data>'.
 
J

Jay Nabonne

5.3.4 (expr.new) paragraph 11 at least calls this form of new expression
"placement syntax of new".
Anyway, according to 18.4.1.1
(lib.new.delete.single) paragraph 12 'operator delete(void*)' only accepts
pointers obtained from 'operator new(std::size_t)'. However, according to
5.3.5 (expr.delete) paragraph 7, a delete expression calls a deallocation
function and the only real operation in this context is
'operator delete(void*)'. This is where things get fuzzy: I can't find a
quote where this is indeed the only option although I'm pretty sure it is.

This effectively means, you cannot use delete expressions on pointers
obtained using the placement syntax of new, i.e. when passing additional
parameters to 'operator new()' during construction. This effectively
implies that you need to explicitly destroy the object and cope with
memory release in a second step.

Ok, that makes sense.
Well, the answer is "yes", there is a way: you could use a function
template which first destroys the object and then releases the memory,
e.g.

template <typename T>
void my_delete(T* ptr) {
{
ptr->~T(); // destroy the object
release(ptr);
}

Unfortunately, the environment we're in doesn't support templates. :( (I
know, I know.) But the technique could still apply, if we wanted to make a
dreaded macro.
If your deallocation function (above called 'release()') needs extra
parameters, you need to obtain them somehow from the pointer, e.g. by
associating them with pointer using e.g. an 'std::map<void*, data>'.

Thanks for the info!

- Jay
 

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

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top