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

is zero-sized new[] allowed? is it guaranteed to return non-NULL?

62 views
Skip to first unread message

Jonathan Thornburg -- remove -animal to reply

unread,
Oct 3, 2005, 5:05:56 PM10/3/05
to
[[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];

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! ]

Alf P. Steinbach

unread,
Oct 4, 2005, 9:41:10 AM10/4/05
to
* Jonathan Thornburg:

>
> Is a 0-sized new[] allocation allowed?

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?

Gene Bushuyev

unread,
Oct 4, 2005, 9:40:49 AM10/4/05
to
"Jonathan Thornburg -- remove -animal to reply" <jth...@aei.mpg-zebra.de>
wrote in message news:3qd48lF...@individual.net...

> [[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
>

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

Bronek Kozicki

unread,
Oct 4, 2005, 9:48:55 AM10/4/05
to
> Is a 0-sized new[] allocation allowed? Is it guaranteed to return
> a non-NULL pointer? That is, for example, given

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;"

Timo Geusch

unread,
Oct 4, 2005, 9:56:10 AM10/4/05
to
Jonathan Thornburg -- remove -animal to reply wrote:

> [[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?

Alberto Ganesh Barbati

unread,
Oct 4, 2005, 9:53:28 AM10/4/05
to
Jonathan Thornburg -- remove -animal to reply wrote:

> 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

Meador Inge

unread,
Oct 4, 2005, 9:55:44 AM10/4/05
to
Jonathan Thornburg -- remove -animal to reply wrote:
> [[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?
It is allowed in that it will compile, but the allocation is not
guaranteed to succeed and if it does succeed the pointer returned is
not guaranteed to be non-null.

> 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."

BigBrian

unread,
Oct 4, 2005, 10:15:29 AM10/4/05
to
With gcc on solaris, the above new does *not* return null. I believe
that new is guarenteed to never return null, it throws exceptions
instead.

-Brian

Martin Bonner

unread,
Oct 4, 2005, 10:11:49 AM10/4/05
to

Jonathan Thornburg -- remove -animal to reply wrote:
> Is a 0-sized new[] allocation allowed? Is it guaranteed to return
> a non-NULL pointer?
Yes and yes.

> 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."

Thomas Richter

unread,
Oct 4, 2005, 10:11:02 AM10/4/05
to
Jonathan Thornburg -- remove -animal to reply wrote:

> 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

Tommaso Galleri

unread,
Oct 4, 2005, 10:15:50 AM10/4/05
to
"Jonathan Thornburg -- remove -animal to reply"
<jth...@aei.mpg-zebra.de> wrote

> 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

Yuri Khan

unread,
Oct 4, 2005, 10:12:46 AM10/4/05
to
Jonathan Thornburg wrote:

> 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?)

Ismail Pazarbasi

unread,
Oct 4, 2005, 10:45:33 AM10/4/05
to
Zero sized new is allowed. But, there is an issue about zero-sized
storage. See standard (3.7.3.1 para 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 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

Andrew Koenig

unread,
Oct 4, 2005, 2:52:34 PM10/4/05
to
"Jonathan Thornburg -- remove -animal to reply" <jth...@aei.mpg-zebra.de>
wrote in message news:3qd48lF...@individual.net...

> 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 :-)

mlimber

unread,
Oct 4, 2005, 3:00:28 PM10/4/05
to
Ismail Pazarbasi wrote:
> Zero sized new is allowed. But, there is an issue about zero-sized
> storage. See standard (3.7.3.1 para 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 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.

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

Meador Inge

unread,
Oct 4, 2005, 3:00:03 PM10/4/05
to

Meador Inge wrote:
> Jonathan Thornburg -- remove -animal to reply wrote:
> > [[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?
> It is allowed in that it will compile, but the allocation is not
> guaranteed to succeed and if it does succeed the pointer returned is
> not guaranteed to be non-null.
>
> > Is it guaranteed to return a non-NULL pointer?
> No, the behavior is undefined.
Whoops, I misread the standard. It is required to return a non-null
pointer.


Allan W

unread,
Oct 5, 2005, 5:02:17 PM10/5/05
to
Yuri Khan wrote:
> (By the way, is it reasonable to assume that the C++ standard, or
> a sufficiently accurate draft thereof, is publicly available?)

You can buy it for a nominal cost.
See the FAQ: -------\
| http://www.gotw.ca/resources/clcm.htm
V

Ismail Pazarbasi

unread,
Oct 5, 2005, 5:04:06 PM10/5/05
to
int* p = NULL;
try
{
p = new int[0];
}
catch(bad_alloc&)
{
cerr << "new failed" << endl;
}

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

Andreas Magnusson

unread,
Oct 6, 2005, 11:11:07 AM10/6/05
to
> I'm wondering whether I need to guard new[] sizes
> that are computed as int with assert(size >= 0) or assert(size > 0)

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

0 new messages