Corresponding forms of new and delete

D

Dave

Hello all,

In the code below, I see the following output:

base::eek:perator new(size_t, int)
base::base()
base::~base()
base::eek:perator delete(void *)

In the case of an exception being thrown during construction, a form of
delete with a signature that corresponds to that of the "new" being used
will be called. However, during a "normal" deallocation, there is no way to
know which version of "new" was previously used, so the usual deallocation
routine is used (I hope I'm using the term "usual" properly here). This is
demonstrated in the output shown above.

When the statement "delete ptr;" is reached, is there a way to cause it to
use "operator delete(void*, int)" as the underlying deallocation routine
rather than "operator delete(void *)"? After all, the usual dellaocation
routine may not do what's right given that the memory was not allocated with
the usual allocation routine! (Again, I hope I'm using the term "usual"
properly.)

I am aware that I could do the following in place of "delete ptr;":

ptr->~base();
base::eek:perator delete(ptr, 243);

However, the point of this article is to see if there is a way to do what I
desire without using explicit calls to the destructor or "operator delete".

Thanks,
Dave


#include <iostream>

using namespace std;

struct base
{
base()
{
cout << "base::base()" << endl;
}

~base()
{
cout << "base::~base()" << endl;
}

void *operator new(size_t size)
{
cout << "base::eek:perator new(size_t)" << endl;
return ::eek:perator new(size);
}

void *operator new(size_t size, int)
{
cout << "base::eek:perator new(size_t, int)" << endl;
return ::eek:perator new(size);
}

void operator delete(void *ptr)
{
cout << "base::eek:perator delete(void *)" << endl;
::eek:perator delete(ptr);
}

void operator delete(void *ptr, int)
{
cout << "base::eek:perator delete(void *, int)" << endl;
::eek:perator delete(ptr);
}
};

int main()
{
base *ptr(new(243) base);

delete ptr;

return 0;
}
 
T

Thomas Richter

Hi,
In comp.lang.c++.moderated Dave said:
Hello all,
In the code below, I see the following output:
base::eek:perator new(size_t, int)
base::base()
base::~base()
base::eek:perator delete(void *)
When the statement "delete ptr;" is reached, is there a way to cause it to
use "operator delete(void*, int)" as the underlying deallocation routine
rather than "operator delete(void *)"?

Short and simple: No.

If you require additional environment information for the memory allocation
or deallocation, you have to store it along with the memory allocated.

A typical solution would be to allocate "one additional int" along with the
requested memory and store the "int argument" of new in there. Then, in
the delete operator, you need to extract it from there.

Basically (unchecked source, so keep care!)

void *base::eek:perator new(size_t s, int x)
{
size_t *mem = (size_t *)malloc(s + sizeof(int));
*mem = x;
return mem+1;
}

void base::eek:perator delete(void *mem)
{
size_t *mymem = (size_t *)mem;
int x = mymem[-1]; // extract private information.
free(mymem-1);
}

The above code still requires work for architectures where the alignment
restrictions for size_t are insufficient for some other objects, but it
should give you the general idea how to solve this problem.

Greetings,
Thomas
 
D

Dhruv

Hello all,

In the code below, I see the following output:

base::eek:perator new(size_t, int)
base::base()
base::~base()
base::eek:perator delete(void *)

In the case of an exception being thrown during construction, a form of
delete with a signature that corresponds to that of the "new" being used
will be called. However, during a "normal" deallocation, there is no way to
know which version of "new" was previously used, so the usual deallocation
routine is used (I hope I'm using the term "usual" properly here). This is
demonstrated in the output shown above.

When the statement "delete ptr;" is reached, is there a way to cause it to
use "operator delete(void*, int)" as the underlying deallocation routine
rather than "operator delete(void *)"? After all, the usual dellaocation
routine may not do what's right given that the memory was not allocated with
the usual allocation routine! (Again, I hope I'm using the term "usual"
properly.)


No, there is no way that I am aware of that can make the operator delete
that you want to be called to get called. This operator delete exists
primarily because of potential failure of the object construction while
calling operator new, as you have already mentioned, but if you want to
call the operator new that takes extra parameters, then while deleting
that object you have to manually do the destroy-deallocate dance. The
reason for this is that you may pass pointers to functions that might
delete this passed pointer, so how can the functions know which operator
delete to call. So, you have to manually deallocate and delete the
memory.


I am aware that I could do the following in place of "delete ptr;":

ptr->~base();
base::eek:perator delete(ptr, 243);

Yes.


Regards,
-Dhruv.
 
R

Roger Orr

Dave said:
Hello all,

In the code below, I see the following output:

base::eek:perator new(size_t, int)
base::base()
base::~base()
base::eek:perator delete(void *)

In the case of an exception being thrown during construction, a form of
delete with a signature that corresponds to that of the "new" being used
will be called. However, during a "normal" deallocation, there is no way to
know which version of "new" was previously used, so the usual deallocation
routine is used (I hope I'm using the term "usual" properly here). This is
demonstrated in the output shown above.

When the statement "delete ptr;" is reached, is there a way to cause it to
use "operator delete(void*, int)" as the underlying deallocation routine
rather than "operator delete(void *)"? After all, the usual dellaocation
routine may not do what's right given that the memory was not allocated with
the usual allocation routine! (Again, I hope I'm using the term "usual"
properly.)

What actual problem are you trying to solve?
Do you need code which transparently handles and destroys heap allocated
objects of both types, or can you separate these two parts of the logic?
Perhaps you can solve the problem with a pair of classes, or by templatizing
on allocation strategy - which may be less likely to be error prone.
Another solution, for example, is to create a pointer-like class which is
responsible for deleting the non-standard object.
If you embed allocation information in your class what does this design say
about objects of this class?

Roger Orr
 

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
474,001
Messages
2,570,254
Members
46,849
Latest member
Fira

Latest Threads

Top