Topic: Defect Report: Placement array new cannot be used portably


Author: AlbertoBarbati@libero.it (Alberto Barbati)
Date: Wed, 15 Sep 2004 03:04:07 GMT
Raw View
Ben Hutchings wrote:
> [ Note: Forwarded to C++ Committee -sdc ]
>
> An implementation may have an unspecified amount of array allocation
> overhead (5.3.4/10 [expr.new]), so that evaluation of a new-expression
> in which the new-type-id is T[n] involves a request for more than n *
> sizeof(T) bytes of storage through the relevant operator new[]
> function.
>
> The placement operator new[] function does not and cannot check
> whether the requested size is less than or equal to the size of the
> provided region of memory (18.4.1.3/5-6 [lib.new.delete.placement]).
> A program using placement array new must calculate what the requested
> size will be in advance.
>
> Therefore any program using placement array new must take into account
> the implementation's array allocation overhead, which cannot be
> obtained or calculated by any portable means.
>

The amount of allocation overhead is added to the size parameter before
operator new[] is called (see footnote 211). Therefore the program need
to know such amount.

Maybe an example can clarify better: suppose T is a type with sizeof(T)
== 16, the overhead is 4 bytes and there are no padding or alignment
problems. Then the expression "new T[10]" would result in calling
operator new[] with a size parameter 164 (or more). The fact that in the
same situation another implementation may ask for a different amount of
memory does not make the program non-portable.

Alberto

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





Author: ben-public-nospam@decadentplace.org.uk (Ben Hutchings)
Date: Thu, 16 Sep 2004 15:09:46 GMT
Raw View
Alberto Barbati wrote:
<snip>
> The amount of allocation overhead is added to the size parameter before
> operator new[] is called (see footnote 211). Therefore the program need
> to know such amount.
>
> Maybe an example can clarify better: suppose T is a type with sizeof(T)
> == 16, the overhead is 4 bytes and there are no padding or alignment
> problems. Then the expression "new T[10]" would result in calling
> operator new[] with a size parameter 164 (or more). The fact that in the
> same situation another implementation may ask for a different amount of
> memory does not make the program non-portable.

I understand all this.  You seem to have missed the word "placement".
Placement new ignores the size parameter; the size must be calculated
by the program beforehand.

--
Ben Hutchings
Quantity is no substitute for quality, but it's the only one we've got.

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





Author: francis@robinton.demon.co.uk (Francis Glassborow)
Date: Thu, 16 Sep 2004 15:11:57 GMT
Raw View
In article <LXK1d.3554$zF3.88139@twister2.libero.it>, Alberto Barbati
<AlbertoBarbati@libero.it> writes
>The amount of allocation overhead is added to the size parameter before
>operator new[] is called (see footnote 211). Therefore the program need
>to know such amount.
>
>Maybe an example can clarify better: suppose T is a type with sizeof(T)
>== 16, the overhead is 4 bytes and there are no padding or alignment
>problems. Then the expression "new T[10]" would result in calling
>operator new[] with a size parameter 164 (or more). The fact that in
>the same situation another implementation may ask for a different
>amount of memory does not make the program non-portable.

Yes, but that also has a problem because one of the reasons for
providing a class version of operator new is to allow allocation from a
special memory pool. The fact that the overhead for an array is unknown
makes it significantly harder to use a special pool for operator new[].


--
Francis Glassborow      ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects

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





Author: AlbertoBarbati@libero.it (Alberto Barbati)
Date: Thu, 16 Sep 2004 16:38:59 GMT
Raw View
Ben Hutchings wrote:
>
> I understand all this.  You seem to have missed the word "placement".
> Placement new ignores the size parameter; the size must be calculated
> by the program beforehand.
>

You're right, I missed the word "placement". I apologize for the noise.

I agree with you that, as it is defined, placement new[] is practically
useless. The worst problem is that according to 5.3.4/12 the amount of
the overhead may vary from one invocation to another. The first option I
see is to provide a mean to obtain at least an upper bound for the size
of such overhead. This could be accomplished by adding a library
function template like:

   namespace std
   {
     template <class T>
     size_t array_new_overhead(size_t n);
   }

such that if the expression new T[n] results in the call

   operator new[](sizeof(T) * n + y)

it's always true that y <= array_new_overhead<T>(n).

I don't think it should be too difficult for compiler implementors to
provide such a template. In fact, I expect most implementations to
return a costant value regardless of T and n ;-) but the definition
deliberately allows a greater flexibility avoiding any change in 5.3.4.

Maybe we should turn this into a proposal?

Regards,

Alberto

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





Author: kon@iki.fi (Kalle Olavi Niemitalo)
Date: Thu, 16 Sep 2004 22:19:10 GMT
Raw View
AlbertoBarbati@libero.it (Alberto Barbati) writes:

> Maybe an example can clarify better: suppose T is a type with
> sizeof(T) == 16, the overhead is 4 bytes and there are no padding or
> alignment problems. Then the expression "new T[10]" would result in
> calling operator new[] with a size parameter 164 (or more).

The problem is with placement new[], where the memory may already
have been allocated before operator new[] is called.

  #include <new>

  struct T {
    char data[16];
  };

  /* conservative guess */
  const std::size_t nonportable_array_overhead = 4 * sizeof (void *);

  int main()
  {
    char buffer[10 * sizeof (T) + nonportable_array_overhead];
    new(buffer) T[10];
  }

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





Author: pavel_vozenilek@yahoo.co.uk ("Pavel Vozenilek")
Date: Thu, 16 Sep 2004 22:19:40 GMT
Raw View
"Ben Hutchings" <ben-public-nospam@decadentplace.org.uk> wrote:

> An implementation may have an unspecified amount of array allocation
> overhead (5.3.4/10 [expr.new]), so that evaluation of a new-expression
> in which the new-type-id is T[n] involves a request for more than n *
> sizeof(T) bytes of storage through the relevant operator new[]
> function.
>
Yes. It was also pointed by Mirek Fiedler in:
http://groups.google.com/groups?c2coff=1&threadm=zgNx9.738%24P14.86551%40newsfep2-win.server.ntli.net
and
http://groups.google.com/groups?c2coff=1&threadm=863cqemr77.fsf%40Zorthluthik.foo

He also cites situation where it caused problem.

/Pavel



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





Author: AlbertoBarbati@libero.it (Alberto Barbati)
Date: Thu, 16 Sep 2004 23:09:43 GMT
Raw View
Francis Glassborow wrote:

>
> Yes, but that also has a problem because one of the reasons for
> providing a class version of operator new is to allow allocation from a
> special memory pool. The fact that the overhead for an array is unknown
> makes it significantly harder to use a special pool for operator new[].
>

I know. Overriding operator new[] is not meant for that. If you want to
use a special memory pool of fixed size objects, you'd better off with a
custom allocator. That doesn't mean that operator new[] isn't useful.
What the OP wanted to stress is that the placement operator new[]
*provided by the implementation* cannot be portably called. Ironic,
isn't it?

Alberto

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





Author: Ben Hutchings <ben-public-nospam@decadentplace.org.uk>
Date: Tue, 14 Sep 2004 22:21:13 +0000 (UTC)
Raw View
[ Note: Forwarded to C++ Committee -sdc ]

An implementation may have an unspecified amount of array allocation
overhead (5.3.4/10 [expr.new]), so that evaluation of a new-expression
in which the new-type-id is T[n] involves a request for more than n *
sizeof(T) bytes of storage through the relevant operator new[]
function.

The placement operator new[] function does not and cannot check
whether the requested size is less than or equal to the size of the
provided region of memory (18.4.1.3/5-6 [lib.new.delete.placement]).
A program using placement array new must calculate what the requested
size will be in advance.

Therefore any program using placement array new must take into account
the implementation's array allocation overhead, which cannot be
obtained or calculated by any portable means.

--
Ben Hutchings
If at first you don't succeed, you're doing about average.



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