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

Overloading new and delete

5 views
Skip to first unread message

Stefan Lueer

unread,
Mar 14, 2000, 3:00:00 AM3/14/00
to
As far as I know, the new-operator can be overloaded and the
overloads can be called from an application. However, if I create
additional deletes, they will only be called, if the corresponding
new throws an exception. I cannot directly call them.

e.g. char *pArray = new (MyHandle) char [50]; ok
delete(MyHandle) [] pArray; not working

Why are delete-overloads not included in the ANSI C++ Standard?

Here is a short description, why I need them:
In an embedded multitasking environment, problems are caused due to
different tasks allocating memory from the heap, fragmenting it.
If new and delete could be overloaded, each task could be given its own
lokal heap. When allocating and releasing memory, a pointer or handle to
the heap could be passed to the operator functions.

Thanks a lot,
Stefan


---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std...@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]


Rob Stewart

unread,
Mar 15, 2000, 3:00:00 AM3/15/00
to
Stefan Lueer wrote:
>
> As far as I know, the new-operator can be overloaded and the
> overloads can be called from an application. However, if I create
> additional deletes, they will only be called, if the corresponding
> new throws an exception. I cannot directly call them.

Correct.

> Why are delete-overloads not included in the ANSI C++ Standard?

The compiler would have quite a job ensuring you matched them
when memory was allocated one place with one new operator, and
deleted elsewhere with a non-corresponding delete operator. This
would require whole program analysis.

> In an embedded multitasking environment, problems are caused due to
> different tasks allocating memory from the heap, fragmenting it.
> If new and delete could be overloaded, each task could be given its own
> lokal heap. When allocating and releasing memory, a pointer or handle to
> the heap could be passed to the operator functions.

Why not overload operator new so it places a thread-unique marker
(or pointer) in the allocated memory? (The returned address can
be offset from the actual allocation to hide the marker.) Then,
operator delete can inspect the marker to determine the correct
deallocation strategy to use.

Alternatively, have operator new allocate in different heaps
based upon the requesting thread. If the range of addresses
managed by each thread's heap could be tracked, operator delete
could know from which heap to free the memory based upon the
address.

Neither of these may be helpful in your embedded environment due
to their memory and/or runtime overhead.

--
Robert Stewart | rob-at-giage-dot-com
Software Engineer | using std::disclaimer;
Giage, Ltd. | http://www.giage.com

Steve Clamage

unread,
Mar 15, 2000, 3:00:00 AM3/15/00
to
Stefan Lueer wrote:
>
> As far as I know, the new-operator can be overloaded and the
> overloads can be called from an application. However, if I create
> additional deletes, they will only be called, if the corresponding
> new throws an exception. I cannot directly call them.
>
> e.g. char *pArray = new (MyHandle) char [50]; ok
> delete(MyHandle) [] pArray; not working
>
> Why are delete-overloads not included in the ANSI C++ Standard?

They are included. You can call any operator delete explicitly.

What is missing is a "placement delete" expression, as in your
example. The reason, as explained in the ARM and in D&E is that
no suitable syntax could be found. The obvious syntax leads to
ambiguities.

You can call the destructor and corresponding operator delete
explicitly:

T* p = new (handle) T(args);
...
p->~T();
operator delete (handle) p;

For an array of objects, you have to write your own loop to
destroy all the elements. Remember to write it to run backwards.

--
Steve Clamage, stephen...@sun.com

Valentin Bonnard

unread,
Mar 15, 2000, 3:00:00 AM3/15/00
to
Rob Stewart wrote:

> Stefan Lueer wrote:

> > As far as I know, the new-operator can be overloaded and the
> > overloads can be called from an application. However, if I create
> > additional deletes, they will only be called, if the corresponding
> > new throws an exception. I cannot directly call them.
>

> Correct.

Not really.

> > Why are delete-overloads not included in the ANSI C++ Standard?
>

> The compiler would have quite a job ensuring you matched them
> when memory was allocated one place with one new operator,

No, absolutly not.

The reason is simply that the syntax

delete (argument-list) expression

is hard to parse, because (something) something resembles
a cast.

> > In an embedded multitasking environment, problems are caused due to
> > different tasks allocating memory from the heap, fragmenting it.

Without a moving gc, memory fragmentation can occur anyway. And you can
implement operator new that way:

map<ThreadID, Pool> pools;

void* operator new (size_t s)
{
// do some locking, then:
return pools[cur_thread()].allocate (s);
}

in order to avoid fragmentation (I am not sure it would have any
positive effects, but you can try).

This is more programmer friendly, as they don't have to
remember from which thread the memory was allocated.

--

Valentin Bonnard

Robert Klemme

unread,
Mar 16, 2000, 3:00:00 AM3/16/00
to

Stefan Lueer schrieb:


>
> As far as I know, the new-operator can be overloaded and the
> overloads can be called from an application. However, if I create
> additional deletes, they will only be called, if the corresponding
> new throws an exception. I cannot directly call them.
>

> e.g. char *pArray = new (MyHandle) char [50]; ok
> delete(MyHandle) [] pArray; not working
>

> Why are delete-overloads not included in the ANSI C++ Standard?
>

> Here is a short description, why I need them:

> In an embedded multitasking environment, problems are caused due to
> different tasks allocating memory from the heap, fragmenting it.

> If new and delete could be overloaded, each task could be given its own
> lokal heap. When allocating and releasing memory, a pointer or handle to
> the heap could be passed to the operator functions.

i do not know about embedded systems, but with posix and other threads
you can store information locally to a thread to get a reference to the
current thread's heap. alternatively you can get the id of the running
thread and have a global object giving you access to the current
thread's heap. so you would not need any additional arguments to the
new operator. maybe this helps?

regards

robert

--
Robert Klemme
Software Engineer
-------------------------------------------------------------
myview technologies GmbH & Co. KG
Riemekestraße 160 ~ D-33106 Paderborn ~ Germany
E-Mail: mailto:robert...@myview.de
Telefon: +49/5251/69090-321 ~ Fax: +49/5251/69090-399
-------------------------------------------------------------

Rob Stewart

unread,
Mar 16, 2000, 3:00:00 AM3/16/00
to
Valentin Bonnard wrote:
>
> Rob Stewart wrote:
>
> > Stefan Lueer wrote:
>
> > > As far as I know, the new-operator can be overloaded and the
> > > overloads can be called from an application. However, if I create
> > > additional deletes, they will only be called, if the corresponding
> > > new throws an exception. I cannot directly call them.
> >
> > Correct.
>
> Not really.

You point out -- below -- that the syntax is ambiguous, so, how
can one call them?

> > > Why are delete-overloads not included in the ANSI C++ Standard?
> >

> > The compiler would have quite a job ensuring you matched them
> > when memory was allocated one place with one new operator,
>
> No, absolutly not.

Perhaps you're right, but saying so doesn't make it so (any more
than my saying the compiler can't means it can't, of course).
Can you elaborate?

> The reason is simply that the syntax
>
> delete (argument-list) expression
>
> is hard to parse, because (something) something resembles
> a cast.

--

Robert Stewart | rob-at-giage-dot-com
Software Engineer | using std::disclaimer;
Giage, Ltd. | http://www.giage.com

---

Christopher Eltschka

unread,
Mar 16, 2000, 3:00:00 AM3/16/00
to
Valentin Bonnard wrote:
>
> Rob Stewart wrote:
>
> > Stefan Lueer wrote:
>
> > > As far as I know, the new-operator can be overloaded and the
> > > overloads can be called from an application. However, if I create
> > > additional deletes, they will only be called, if the corresponding
> > > new throws an exception. I cannot directly call them.
> >
> > Correct.
>
> Not really.
>
> > > Why are delete-overloads not included in the ANSI C++ Standard?
> >
> > The compiler would have quite a job ensuring you matched them
> > when memory was allocated one place with one new operator,
>
> No, absolutly not.
>
> The reason is simply that the syntax
>
> delete (argument-list) expression
>
> is hard to parse, because (something) something resembles
> a cast.

But a cast always looks like (type) expression, never like
(expression) expression. And the compiler must be able to tell
the difference, to distinguish between (long)*foo and
int bar;(bar)*foo, where the first one is a cast of
dereferenced foo, while the second one is a multiplication.

Indeed, distinguishing types and expressions is crucial for C++
parsing (guess why "typename" is needed).

However, there's an ambiguity for pure expressions:

class X {}
X* operator*(X&);
X* operator*(int, X const&);

int a;
X x;

delete (a) *x;
// placement delete(int) on *x, or normal delete on (a)*x?

[...]

Steven E. Harris

unread,
Mar 16, 2000, 3:00:00 AM3/16/00
to
Steve Clamage <stephen...@sun.com> writes:

> For an array of objects, you have to write your own loop to
> destroy all the elements. Remember to write it to run backwards.

Why must the loop run backwards?

--
Steven E. Harris
Primus Knowledge Solutions, Inc.
http://www.primus.com

Valentin Bonnard

unread,
Mar 17, 2000, 3:00:00 AM3/17/00
to
Rob Stewart wrote:

> Valentin Bonnard wrote:
> >
> > Rob Stewart wrote:
> >
> > > Stefan Lueer wrote:
> >
> > > > As far as I know, the new-operator can be overloaded and the
> > > > overloads can be called from an application. However, if I create
> > > > additional deletes, they will only be called, if the corresponding
> > > > new throws an exception. I cannot directly call them.
> > >
> > > Correct.
> >
> > Not really.
>

> You point out -- below -- that the syntax is ambiguous, so, how
> can one call them?

A call to the delete operator is just a call to the dtor followed
by a call to operator delete:

delete (args) p;

becomes

try {
p->~T();
} catch (...) {
operator delete (p, args);
throw;
}
operator delete (p, args);

> > > > Why are delete-overloads not included in the ANSI C++ Standard?
> > >
> > > The compiler would have quite a job ensuring you matched them
> > > when memory was allocated one place with one new operator,
> >
> > No, absolutly not.
>

> Perhaps you're right, but saying so doesn't make it so (any more
> than my saying the compiler can't means it can't, of course).
> Can you elaborate?

Why on earth would a compiler need to ensure that the correct
operator delete is called ? The whole point of the additional
arguments of operator delete is to supply information the
compiler does not have.

In the following incorrect code:

int i;
int* p = &i;
delete p;

the compiler doesn't have to check that p is actually a pointer
to something allocated with new.

In the following correct code:

char* p = new (nothrow) char (' ');
delete p;

The memory is _not_ desallocated with the corresponding
operator delete; the compiler cannot reject code which
calls a non-corresponding operator delete.

Of course the compiler cannot statically check that the correct
operator delete is called, since pointer types contain no
information relating to how the pointed-to data was allocated,
if it was dynamically allocated at all.

--

Valentin Bonnard

Rob Stewart

unread,
Mar 17, 2000, 3:00:00 AM3/17/00
to
Valentin Bonnard wrote:
>
> Rob Stewart wrote:
>
> > Valentin Bonnard wrote:
> > >
> > > Rob Stewart wrote:
> > >
> > > > Stefan Lueer wrote:
> > >
> > > > > As far as I know, the new-operator can be overloaded and the
> > > > > overloads can be called from an application. However, if I create
> > > > > additional deletes, they will only be called, if the corresponding
> > > > > new throws an exception. I cannot directly call them.
> > > >
> > > > Correct.
> > >
> > > Not really.
> >
> > You point out -- below -- that the syntax is ambiguous, so, how
> > can one call them?
>
> A call to the delete operator is just a call to the dtor followed
> by a call to operator delete:

[code snipped]

That's cheating. We were discussing whether you could call the
overloaded delete operators. You can't. We weren't discussing
whether you could write equivalent code.

> > > > > Why are delete-overloads not included in the ANSI C++ Standard?
> > > >
> > > > The compiler would have quite a job ensuring you matched them
> > > > when memory was allocated one place with one new operator,
> > >
> > > No, absolutly not.
> >

> > Can you elaborate?
>
> Why on earth would a compiler need to ensure that the correct
> operator delete is called ? The whole point of the additional
> arguments of operator delete is to supply information the
> compiler does not have.

Fair enough. I was stabbing in the dark to provide an answer
anyway.

--
Robert Stewart | rob-at-giage-dot-com
Software Engineer | using std::disclaimer;
Giage, Ltd. | http://www.giage.com

---

Yura Koblents-Mishke

unread,
Mar 18, 2000, 3:00:00 AM3/18/00
to

"Steven E. Harris" wrote:
>
> Steve Clamage <stephen...@sun.com> writes:
>
> > For an array of objects, you have to write your own loop to
> > destroy all the elements. Remember to write it to run backwards.
>
> Why must the loop run backwards?
>

The class data members (and the parents classes) must
be destructed in the order opposite to the order they
were constructed.

The same logic here?..

Francis Glassborow

unread,
Mar 20, 2000, 3:00:00 AM3/20/00
to
In article <38D31547...@pop3.concentric.net>, Yura Koblents-Mishke
<yu...@concentric.net> writes

>"Steven E. Harris" wrote:
>>
>> Steve Clamage <stephen...@sun.com> writes:
>>
>> > For an array of objects, you have to write your own loop to
>> > destroy all the elements. Remember to write it to run backwards.
>>
>> Why must the loop run backwards?
>>
>
>The class data members (and the parents classes) must
>be destructed in the order opposite to the order they
>were constructed.
>
>The same logic here?..

Actually, unless there is some specific way in which the elements are
related there is no constraint on the order of deletion of dynamically
created objects.


Francis Glassborow Journal Editor, Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

Michiel Salters

unread,
Mar 20, 2000, 3:00:00 AM3/20/00
to
"Steven E. Harris" wrote:

> Steve Clamage <stephen...@sun.com> writes:

> > For an array of objects, you have to write your own loop to
> > destroy all the elements. Remember to write it to run backwards.

> Why must the loop run backwards?

Probably easier on the memory management (MM). Imagine there are
no other objects intermixed:

-> ...Used | Obj[0] | Obj[1] | Obj[2] | Obj[3] | Obj[4] | Free..... ->
If you delete from the end, you have only one contigous free space,
and the MM can merge all memory reclaimed with it. If you delete from
the beginning, the MM must start by creating a new free block, and
when you delete Obj[4], the MM must merge that space with two free
blocks.

Michiel Salters

Steve Clamage

unread,
Mar 23, 2000, 3:00:00 AM3/23/00
to
On Mon, 20 Mar 2000 23:35:23 CST, Michiel Salters <sal...@lucent.com>
wrote:

>"Steven E. Harris" wrote:
>
>> Steve Clamage <stephen...@sun.com> writes:
>
>> > For an array of objects, you have to write your own loop to
>> > destroy all the elements. Remember to write it to run backwards.
>
>> Why must the loop run backwards?
>
>Probably easier on the memory management (MM).

No, it's because that's how delete[] is defined to work, and your
replacement should work the same way.

Except for objects created on the heap, objects created in a scope are
destroyed in the reverse order of their construction.

---
Steve Clamage, stephen...@sun.com

Andrei Alexandrescu

unread,
Mar 24, 2000, 3:00:00 AM3/24/00
to
Steve Clamage <stephen...@sun.com> wrote in message
news:pergds0vj81kdq54p...@4ax.com...

> Except for objects created on the heap, objects created in a scope are
> destroyed in the reverse order of their construction.

What about elements in a vector, Steve? Are they destroyed in reverse order,
normal order, or any of these? Thanks!


Andrei

ka...@gabi-soft.de

unread,
Mar 27, 2000, 3:00:00 AM3/27/00
to
Steve Clamage <stephen...@sun.com> writes:

|> On Mon, 20 Mar 2000 23:35:23 CST, Michiel Salters <sal...@lucent.com>
|> wrote:

|> >"Steven E. Harris" wrote:

|> >> Steve Clamage <stephen...@sun.com> writes:

|> >> > For an array of objects, you have to write your own loop to
|> >> > destroy all the elements. Remember to write it to run backwards.

|> >> Why must the loop run backwards?

|> >Probably easier on the memory management (MM).

|> No, it's because that's how delete[] is defined to work, and your
|> replacement should work the same way.

|> Except for objects created on the heap, objects created in a scope are


|> destroyed in the reverse order of their construction.

I'm not sure what the standard says, but this isn't true in any compiler
I've seen, and I'm pretty sure it isn't the intent. Consider:

{
A anA ;
B aB ;
new ( &anA ) A ;
}

In this case, anA is constructed *after* aB, but every compiler I know
of will destruct it after destructing aB. (Since the placement new
could actually be in a function in another function, invisible to the
compiler when this function is being compiled, it is hard to see how it
could be otherwise.)

So shouldn't the statement be "Except for objects explicitly created
with a new expression..."?

Also, I think that this guarantee only holds for the language itself,
and not for the library. Requiring it in the library could make the
implementation of e.g. list unreasonably complicated.

--
James Kanze mailto:ka...@gabi-soft.de
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelhüttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627

ka...@gabi-soft.de

unread,
Mar 28, 2000, 3:00:00 AM3/28/00
to
"Andrei Alexandrescu" <andre...@hotmail.com> writes:

|> Steve Clamage <stephen...@sun.com> wrote in message
|> news:pergds0vj81kdq54p...@4ax.com...

|> > Except for objects created on the heap, objects created in a scope are
|> > destroyed in the reverse order of their construction.

|> What about elements in a vector, Steve? Are they destroyed in


|> reverse order, normal order, or any of these? Thanks!

I think that the standard is silent about this, but I really don't think
it can impose an order. What would it mean after an arbitrary sequence
of insert and erase?

Claude Quézel

unread,
Mar 31, 2000, 3:00:00 AM3/31/00
to

Maybe M. Clamage wanted to express that vector objects are constructed in the
order in wich they appear in the container and destroyed in the reverse order.

class A {
// ...
};

// ...

{// scope begin
A vect1[10]; // 10 A objects are constructed. Order is well defined 0, 1, ... 9.

std::vector<A> vect2(10); // 10 A objects are constructed. Order is well defined
0, 1, ... 9.
myVector<A> vect3(10); // 10 A objects are constructed. Order implementation
defined.


// (vect3 going out of scope) 10 A objects are destructed. Order is
implementation defined.
// (vect2 going out of scope) 10 A objects are destructed. Order is well defined
9, 8, ... 0.
// (vect1 going out of scope) 10 A objects are destructed. Order is well defined
9, 8, ... 0.
}// scope end

To obtain the same behaviour with a library defined container (ex:
std::vector/myVector) as C/C++ arrays , the implementer must/should construct
objects in the order the appear in the container and destroy them in reverse
order.

ka...@gabi-soft.de wrote:

--

Claude Quézel (claude...@syntell.corba)
anti-spam: replace corba by com in private replies

ka...@gabi-soft.de

unread,
Apr 3, 2000, 3:00:00 AM4/3/00
to
"Claude Quézel" <Claude...@Syntell.corba> writes:

|> Maybe M. Clamage wanted to express that vector objects are
|> constructed in the order in wich they appear in the container and
|> destroyed in the reverse order.

I don't think so. Unless I've missed something, the order of
destruction is not specified by the standard. And the order of
construction is the order of insertion, which can still be arbitrary.

Mike Nordell

unread,
Apr 6, 2000, 3:00:00 AM4/6/00
to
Valentin Bonnard <Bonn...@wanadoo.fr> wrote:

>Why on earth would a compiler need to ensure that the correct
>operator delete is called ?

Orthogonality. You can create numerous global operator new overloads,
but they all get routed to _one common_ delete operator. I think the
last point is the real problem (and allocators won't solve this).

Creating a more-or-less "invisible" (i.e. non-source-intrusive except
for the overloaded operator new function) persistent storage, using
different heaps using different global operator new overloads, it
became an issue. Since I can't have *my* operator delete called
"automatically", I have to install a global operator delete to see
what heap the object is in, and if it's mine I call one of my private
delete operators, otherwise the "normal" global delete.

This is however not really the compilers problem, as it is a
problem/fact of the language.

--
Mike
Please followup to the group
X-Replace-Address
X-No-Reject-Notice

0 new messages