Is a 0-sized new[] allocation allowed? Is it guaranteed to return
a non-NULL pointer? That is, for example, given
#include <cstdlib>
int foo(size_t N)
{
int* const p = new int[N];
int sum = 0;
for (size_t i = 0 ; i < N ; ++i)
{
// do something with p[i]
}
return (p == NULL) ? 69 : 105;
}
is it legal to execute the call foo(0) ? (Note that the code won't
try to access the resulting 0-sized array if the new[] succeeds.)
Should foo(0) throw bad_alloc or any other exception? And if
foo(0) is legal and doesn't throw, is it guaranteed to return 105?
None of my usual C++ references (C++PL3, Lippman/Lajoie3, D&EC++,
Myers, EC++, MEC++, EC++Style) seem to discuss this point.
thanks, ciao,
--
-- "Jonathan Thornburg (remove -animal to reply)" <jth...@aei.mpg-zebra.de>
Max-Planck-Institut fuer Gravitationsphysik (Albert-Einstein-Institut),
Golm, Germany, "Old Europe" http://www.aei.mpg.de/~jthorn/home.html
"Washing one's hands of the conflict between the powerful and the
powerless means to side with the powerful, not to be neutral."
-- quote by Freire / poster by Oxfam
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Yes.
> Is it guaranteed to return a non-NULL pointer?
Yes, for the default allocator.
> None of my usual C++ references (C++PL3, Lippman/Lajoie3, D&EC++,
> Myers, EC++, MEC++, EC++Style) seem to discuss this point.
The standard does.
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Yes, it is allowed, but it is not guaranteed to succeed. See 3.7.3.1: "Even
if the size of the space requested is zero, the request can fail. If the
request succeeds, the value returned shall be a nonnull pointer value (4.10)
p0 different from any previously returned value p1, unless that value p1 was
subsequently passed to an operator delete. The effect of dereferencing a
pointer returned as a request for zero size is undefined.32)
__________________
32) The intent is to have operator new() implementable by calling malloc()
or calloc(), so the rules are substantially the same. C++ differs from C in
requiring a zero request to return a non-null pointer."
- gene
yes, yes.
> Should foo(0) throw bad_alloc or any other exception? And if
> foo(0) is legal and doesn't throw, is it guaranteed to return 105?
it might, yes. See discussion "Behavior of new T[0]" , started 27th Sep
(this year)
B.
PS. you forgot "delete[] p;"
> [[This is not a homework assignment -- I have a genuine "real-world"
> piece of code, and I'm wondering whether I need to guard new[] sizes
> that are computed as int with assert(size >= 0) or assert(size >
> 0) .]]
>
> Is a 0-sized new[] allocation allowed? Is it guaranteed to return
> a non-NULL pointer? That is, for example, given
>
> #include <cstdlib>
>
> int foo(size_t N)
> {
> int* const p = new int[N];
What's stopping you from replacing this line with the line below?
int* const p = (N > 0) ? new int[N] : 0;
>
> int sum = 0;
> for (size_t i = 0 ; i < N ; ++i)
> {
> // do something with p[i]
> }
>
> return (p == NULL) ? 69 : 105;
> }
In the context of your program this would still work and it would do
away with the overhead of an unnecessary call to new.
BTW, aren't you also missing a delete[] in the code above?
> Is a 0-sized new[] allocation allowed?
Yes. §5.3.4/7: "When the value of the expression in a
direct-new-declarator is zero, the allocation function is called to
allocate an array with no elements."
> Is it guaranteed to return a non-NULL pointer?
It may fail by throwing an exception. If it doesn't throw an exception,
the result is guaranteed to be non-null. (To be nit-picking, this is
true for the default implementation of the global allocation function.
If the program supplies a different, ill-behaved, allocator function
which returns a null-pointer instead of throwing, the new-expression
will return a null-pointer, §5.3.4/13).
Ganesh
> Is it guaranteed to return a non-NULL pointer?
No, the behavior is undefined.
The relevant section of the C++ Standard for this is 3.7.3.1. Clause 2
of the aforementioned section makes the following claims about passing
zero to an allocation function:
"Even if the size of the space requested is zero, the request can
fail."
"The effect of dereferencing a pointer returned as a request for zero
size is undefined."
-Brian
> None of my usual C++ references (C++PL3, Lippman/Lajoie3, D&EC++,
> Myers, EC++, MEC++, EC++Style) seem to discuss this point.
Given that you said this is a real world problem, you ought to persuade
your boss to shell the few dollars to buy a PDF of the actual C++
standard to add to your reference list. In that you would find:
5.3.4 s7: "When the value of the expression in a direct-new-declarator
is zero, the allocation function is called to allocate an array with no
elements. The pointer returned by the new-expression is nonnull."
> Is a 0-sized new[] allocation allowed?
Yes.
> Is it guaranteed to return
> a non-NULL pointer?
Yes.
> That is, for example, given
>
> #include <cstdlib>
>
> int foo(size_t N)
> {
> int* const p = new int[N];
>
> int sum = 0;
> for (size_t i = 0 ; i < N ; ++i)
> {
> // do something with p[i]
> }
>
> return (p == NULL) ? 69 : 105;
> }
>
> is it legal to execute the call foo(0) ?
Yes.
(Note that the code won't
> try to access the resulting 0-sized array if the new[] succeeds.)
> Should foo(0) throw bad_alloc or any other exception?
In the way it is formulated here, it won't, unless it runs out of
memory. (Yes, allocating zero elements costs memory). If you want to
throw an exception, then this is of course your choice, but the code
doesn't do this itself.
> And if
> foo(0) is legal and doesn't throw, is it guaranteed to return 105?
Yes.
Greetings,
Thomas
> Is a 0-sized new[] allocation allowed? Is it guaranteed to return
> a non-NULL pointer?
> None of my usual C++ references (C++PL3, Lippman/Lajoie3, D&EC++,
> Myers, EC++, MEC++, EC++Style) seem to discuss this point.
3.7.3.1
...
If the size of the space required is zero, the value returned shall not
be a null pointer value (4.10). The result of dereferencing a pointer
returned as a request for zero size are undefined (32).
...
(32) = The intent is to have operator new() implementable by calling
malloc() or calloc(), so the rules are substantially the same. C++
differs from C in requiring a zero request to return a non-null pointer.
...
Tommaso
--
Posted via Mailgate.ORG Server - http://www.Mailgate.ORG
> Is a 0-sized new[] allocation allowed?
Yes. Thus says the standard:
5.3.4/1: [...]
<direct-new-declarator>:
'[' <expression> ']'
<direct-new-declarator> '[' <constant-expression> ']'
[...]
5.3.4/6: [...] The <expression> in a <direct-new-declarator> shall have
integral or enumeration type (3.9.1) with a non-negative value. [...]
5.3.4/7: When the value of the <expression> in a
<direct-new-declarator> is zero, the allocation function is called to
allocate an array with no elements.
> Is it guaranteed to return a non-NULL pointer?
Yes:
5.3.4/8: A new-expression obtains storage for the object by calling an
allocation function (3.7.3.1).
3.7.3.1/2: [...] Even if the size of the space requested is zero, the
request can fail. If the request succeeds, the value returned shall be
a non-null pointer value (4.10) p0 different from any previously
returned value p1, unless that value p1 was subsequently passed to an
operator delete. [...]
> That is, for example, given
>
> #include <cstdlib>
>
> int foo(size_t N)
> {
> int* const p = new int[N];
>
> int sum = 0;
> for (size_t i = 0 ; i < N ; ++i)
> {
> // do something with p[i]
> }
>
> return (p == NULL) ? 69 : 105;
> }
>
> is it legal to execute the call foo(0)?
Is. But you have a memory leak of 0 ints here :)
> Should foo(0) throw bad_alloc or any other exception?
It may throw std::bad_alloc if there is not enough memory to allocate 0
ints, see reference to 3.7.3.1/2 above.
> And if foo(0) is legal and doesn't throw, is it guaranteed to return 105?
It is, assuming that new is not redefined in a non-conforming way.
> None of my usual C++ references (C++PL3, Lippman/Lajoie3, D&EC++,
> Myers, EC++, MEC++, EC++Style) seem to discuss this point.
In issues like this, you're better off referring directly to the
standard, rather than interpretations, even by
Stroustroup/Meyers/Sutter.
(By the way, is it reasonable to assume that the C++ standard, or a
sufficiently accurate draft thereof, is publicly available?)
...Even if the size of the space requested is zero, the request can
fail. If the request succeeds, the value returned shall be a nonnull
pointer value (4.10) p0 different from any previously returned value
p1, unless that value p1 was subsequently
passed to an operator delete. The effect of dereferencing a pointer
returned as a request for
zero size is undefined.32)
32) The intent is to have operator new() implementable by calling
malloc() or calloc(), so the rules are substantially the
same. C + + differs from C in requiring a zero request to return a
non-null pointer.
It's not guaranteed to return a valid pointer, as stated above.
Ismail
> None of my usual C++ references (C++PL3, Lippman/Lajoie3, D&EC++,
> Myers, EC++, MEC++, EC++Style) seem to discuss this point.
Lippman/Lajoie/Moo4 does :-)
But it is guaranteed to return a pointer that can be and must be
deleted (assuming no exception is thrown). Only dereferencing the
pointer is undefined.
Cheers! --M
You can buy it for a nominal cost.
See the FAQ: -------\
| http://www.gotw.ca/resources/clcm.htm
V
delete p; // deleting NULL is legal
I got what you mean (in case new didn't throw), and I think it's the
best case. What standard actually says, as you pointed out, zero sized
new is OK, but dereferencing it is undefined. The rest of the new
characteristics are the same.
Above example is a good way to deal with 'new', I think (it can be
enhanced, may be it can be written with template as well). new can
throw, may not return a valid pointer, etc. One should never rely on
new, "even if the requested size is zero".
Ismail
Given that new[0] is defined I personally think this answer is in your
program. Does it ever make sense in your program to allocate a
zero-length array? Or could it be a sign of an error elsewhere in the
code?
If it would never make sense to have a zero-length array I would
definitely use the later assert even though new[0] is defined according
to the C++-standard, just to find more bugs.
/Andreas