Topic: new and delete


Author: chopps@water.emich.edu (Christian E. Hopps)
Date: 1995/09/14
Raw View
In article <9525704.3898@mulga.cs.mu.OZ.AU>, fjh@mundil.cs.mu.OZ.AU
(Fergus Henderson) wrote:

> You can call such an operator delete using an ordinary function call,
> e.g.
>
>         operator delete(p, q);

Oops, I guess everyone knows how often I use the more explicit
operator syntax now. :)

> >Well 5.3.4(*) references 3.7.3.2(**) which says that for global
> >operator delete only one type is valid (void operator delete(void*))
> >but for class members one can define two, namely:
> >
> >    void operator delete(void*, size_t);
> >    void operator delete(void*);
>
> 3.7.3.2 is wrong, or at least misleading.
> You are allowed to define operator delete functions with any
> number of arguments.

Yes, 3.7.3.2 was at the root of my confusion.  After posting and
then later re-reading my own post I realized this.

I think that 3.7.3.2 is misleading.  I sent some mail to steve
talking about this.  I think it can be cleaned up by eliminating
the second sentance of paragraph 2 and being more explicit when
talking about the two member functions in question (i.e. not
using language that makes them seem like the only possible choices.)
---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]





Author: wald@theory.lcs.mit.edu (David Wald)
Date: 1995/09/14
Raw View
In article <MATT.95Sep13110057@physics2.Berkeley.EDU>
clamage@Eng.Sun.COM (Steve Clamage) writes:
>I haven't found any contradictory statements about this in the WP,
>including what you referenced in the original article. The WP does
>not mention all the possibilities in each place where it talks
>about deallocation, so perhaps that is confusing. But if you do
>find wording that seems contradictory or is in particular confusing
>(as opposed to the subject being confusing), please let me know,
>or post it here.

I certainly found the public draft confusing in this regard.  Although
the term "placement delete" is used in a couple of places, I found no
clear definition of the term, nor was there a corresponding entry in
the index.  [basic.stc.dynamic.deallocation] (3.7.3.2) only mentions
"placement delete" in reference to delete(void*,size_t);
[expr.new](5.3.4), in turn, seems to refer to 3.7.3.2 for a definition
of "placement delete".  Now that I know what I'm looking for, I
suppose that all the definitions are there to be inferred, but they're
hard to see if you don't already know what they're going to say.

-David
--
============================================================================
David Wald      http://theory.lcs.mit.edu/~wald/     wald@theory.lcs.mit.edu
   "Blessed are the peacocks, for they shall be called sonship of God"
             -- Matt 5:9, from a faulty QuickVerse 2.0
============================================================================

---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]





Author: chopps@water.emich.edu (Christian E. Hopps)
Date: 1995/09/13
Raw View
I have recently been working with a compiler vendor to fix some bugs regarding
exceptions thrown during construction of "new" allocated objects.

I have become totally confused as to the appropriate behavior when
dealing with new-placement expressions.  Most of the confusion
stems from a lack of clarity in the WP (this could just be me though.)

First section 5.3.4(*) mentions an operator delete() that has almost the
same type as the placement operator new() being used (all but the first
argument matching.)

Does this mean if I have e.g. void* operator new(size_t, void*)
I can have an operator delete(void*, void*)?  Given the grammar
for actually using "delete" there is no way to call this operator
delete.  (other than throwing an exception from a constructor :)

Well 5.3.4(*) references 3.7.3.2(**) which says that for global
operator delete only one type is valid (void operator delete(void*))
but for class members one can define two, namely:

    void operator delete(void*, size_t);
    void operator delete(void*);

If both are given then the two argument version is a placement
version.  Otherwise the one declared is a normal version and there
is no placement (does that mean that the name lookup mentioned in
5.3.4 should fail if only "operator delete(void*, size_t) is found?)

Hmm.. so basically the only way that the "name lookup" mentioned in
5.3.4 will succeed is if I have used an operator new declared as such:

    void* operator new(size_t, size_t);

Thats not very common.

The fact that clause 20 of 5.3.4 exists at all makes it hard to believe
that this is the case.

I'm basically lost jumping around the WP at this point.  Can someone
clarify what kinds of operator delete's are allowed and exactly what
is supposed to occur when an object constructed from a placement-new
throws while constructing?

Thanks,
Chris.

* 5.3.4 [...]
18 If the constructor throws an exception and the new-expression
contains a new-placement, a name lookup is performed on the name
of operator delete in the scope of this new-expression. If the
lookup succeeds and exactly one of the declarations found matches
the declaration of that placement operator new, then the matching
placement operator delete shall be called (3.7.3.2).

19 A declaration of placement operator delete matches the declaration
of a placement operator new when it has the same number of parameters
and all parameter types except the first are identical disregarding
top-level cv-qualifiers.

20 If placement operator delete is called, it is passed the same
arguments as were passed to placement operator new. If the
implementation is allowed to make a copy of an argument as part
of the placement new call, it is allowed to make a copy (of the
same original value) as part of the placement delete call, or
to reuse the copy made as part of the placement new call. If the
copy is elided in one place, it need not be elided in the other.

** 3.7.3.2
1 Like allocation functions, deallocation functions can be static
class member functions or global functions.

2 Each deallocation function shall return void and its first parameter
shall be void*. For class member deallocation functions, a second
parameter of type size_t may be added. If both versions are declared
in the same class, the one-parameter form is the usual deallocation
function and the two-parameter form is used for placement delete
(5.3.4). If the second version is declared but not the first, it is
the usual deallocation function, not placement delete.
---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]





Author: clamage@Eng.Sun.COM (Steve Clamage)
Date: 1995/09/13
Raw View
chopps@water.emich.edu (Christian E. Hopps) writes:

>I have recently been working with a compiler vendor to fix some bugs regarding
>exceptions thrown during construction of "new" allocated objects.

>I have become totally confused as to the appropriate behavior when
>dealing with new-placement expressions.  Most of the confusion
>stems from a lack of clarity in the WP (this could just be me though.)

I think the WP is reasonably clear, but the subject is complicated.

Operator new must have a first argument of type size_t, and operator
delete must have a first argument of type void*. If the remaining
arguments match, the placement new and placement delete match.
(Except for the case noted below.)

The complication is that a class may have a member function
 void operator delete(void*, size_t); // #2

If that class ALSO has a member function
 void operator delete(void*);         // #1
then #2 is a placement-delete.

If that class does NOT also have a member #1, then #2 is not a
placement delete, but is an ordinary delete. (The old rule was
that a class could not have both, since delete could not be
overloaded. Now it can be overloaded.)

The only time this causes confusion is when
- you have a placement-new member function
 void* operator new(size_t, size_t)
- AND you have a member function
 void operator delete(void*, size_t)
- AND you do NOT have a member function
 void operator delete(void*)

In that one case, the operator delete looks like it matches the placement
new, but it doesn't; there is no match. In all other cases, the
argument test alone determines the match.

I haven't found any contradictory statements about this in the WP,
including what you referenced in the original article. The WP does
not mention all the possibilities in each place where it talks
about deallocation, so perhaps that is confusing. But if you do
find wording that seems contradictory or is in particular confusing
(as opposed to the subject being confusing), please let me know,
or post it here.
--
Steve Clamage, stephen.clamage@eng.sun.com

---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]





Author: fjh@mundil.cs.mu.OZ.AU (Fergus Henderson)
Date: 1995/09/13
Raw View
chopps@water.emich.edu (Christian E. Hopps) writes:

>I have recently been working with a compiler vendor to fix some bugs regarding
>exceptions thrown during construction of "new" allocated objects.
>
>I have become totally confused as to the appropriate behavior when
>dealing with new-placement expressions.  Most of the confusion
>stems from a lack of clarity in the WP (this could just be me though.)
>
>First section 5.3.4(*) mentions an operator delete() that has almost the
>same type as the placement operator new() being used (all but the first
>argument matching.)
>
>Does this mean if I have e.g. void* operator new(size_t, void*)
>I can have an operator delete(void*, void*)?

Yes.

>Given the grammar
>for actually using "delete" there is no way to call this operator
>delete.  (other than throwing an exception from a constructor :)

You can call such an operator delete using an ordinary function call,
e.g.

 operator delete(p, q);

But there is no special "placement delete" syntax, so even though
you can write

 q = new (p) T;

you can't write

 delete (p) q;

The reason for this rather inconsistent state of affairs is that
various nasty parsing ambiguities would result if that syntax were
allowed.

>Well 5.3.4(*) references 3.7.3.2(**) which says that for global
>operator delete only one type is valid (void operator delete(void*))
>but for class members one can define two, namely:
>
>    void operator delete(void*, size_t);
>    void operator delete(void*);

3.7.3.2 is wrong, or at least misleading.
You are allowed to define operator delete functions with any
number of arguments.

>exactly what is supposed to occur when an object constructed from a
>placement-new throws while constructing?

I think the WP is reasonably clear on this: if there is a matching
operator delete function, it is called, otherwise nothing happens.

--
Fergus Henderson             |  #define x t=a[i],a[i]=a[m],a[m]=t/* use -O */
                             |  char a[]=" 12345678";main(m,i,j,t){for(i=m;i<
fjh@cs.mu.oz.au              |  9;x,i++)for(x,j=m;--j?(t=a[m-j]-a[m])-j&&t+j:
http://www.cs.mu.oz.au/~fjh  |  main(m+1)*0;);m-9||puts(a+1);} /* 8 queens */

[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]