7

This is similar to What does zero-sized array allocation do/mean?

I have following code

int *p = new int[0];
delete []p;

p gets an address and gets deleted properly.

My question is: Why allocation of zero bytes is allowed by c++ Standard in the first place? Why doesn't it throw bad_alloc or some special exception ?

I think, It is just postponing the catastrophic failure, making programmer's life difficult. Because if size to be allocated is calculated at run time and if programmer assumes its allocated properly and tries to write something to that memory, ends up corrupting memory !!! and Crash may happen some where else in the code.

EDIT: How much memory it allocates upon zero size request ?

Community
  • 1
  • 1
bjskishore123
  • 5,847
  • 9
  • 37
  • 65
  • 1
    It's not an exact duplicate, but see http://stackoverflow.com/questions/1087042/c-new-int0-will-it-allocate-memory for more information. – KevenK Nov 09 '10 at 12:09
  • 1
    Also relevant: http://stackoverflow.com/questions/1259803/what-does-zero-sized-array-allocation-do-mean – KevenK Nov 09 '10 at 12:11
  • @KevenK : The link in your comment is already present in the OP. – Prasoon Saurav Nov 09 '10 at 12:19
  • Why should it be invalid? Invalid is only defining it on stack: int i[0]; (Invalid but useful. This could be used for compile time checking e.g int dummychecker[ sizeof(int)==4?1:0 ]; - causes compile error on machines where int is not 4 bytes) – Valentin Heinitz Nov 09 '10 at 13:15
  • @Prasoon Saurav : Not that it's terribly important now, but I don't believe there were any links in the post when I saw it and gathered information. I believe the link was added in the edit which may have happened before or after I posted the link (I'm not sure) but the link did not exist in my browser's version of this question. Not that it's terribly important, I'd just prefer that people believed I was able to read and wasn't just re-linking the same question. Besides, this is a comment, I get no rep for trying to help here. – KevenK Nov 09 '10 at 13:26
  • @KevenK: Link i already posted in first version of question itself :). Anyways, never mind. Thank you for your helping nature. Keep it up :) – bjskishore123 Nov 09 '10 at 16:15
  • @bjskishore123 : Apparently, then, I cannot read. Don't tell my father, he may be embarrassed. – KevenK Nov 09 '10 at 16:19

5 Answers5

6

Why would you want it to fail? If the programmer tries to read/write to non-existent elements, then that is an error. The initial allocation is not (this is no different to e.g. int *p = new int[1]; p[1] = 5;).

Oliver Charlesworth
  • 252,669
  • 29
  • 530
  • 650
  • @Oli Charlesworth: Whats the use of granting some memory, when it can't be used ? so, i thought better to deny the allocation request instead. – bjskishore123 Nov 09 '10 at 12:13
  • @Oli Charlesworth: Also, pls check the links provided by Kevenk. – bjskishore123 Nov 09 '10 at 12:16
  • @bjskishore123: What's the use? So that there doesn't have to be a special case for `new T[N]` when `N == 0`. If `new` returned `NULL`, or threw an exception in this case, then that would make it non-transparent, which would be a pain. See @Patrick's answer for two good examples of this. – Oliver Charlesworth Nov 09 '10 at 12:22
  • 2
    @bjskishore123: the address returned will be unique. There are many datastructures which require or expect unique values, e.g. `std::map`. – MSalters Nov 09 '10 at 12:24
  • @Oli Charlesworth: Fine, how to find out this kind of bug early in the development cycle ? as i can't distinguish between allocation success and failure. – bjskishore123 Nov 09 '10 at 12:33
  • @bjskishore123: What is the bug? Do you mean accidentally writing `new int[0]` instead of `new int[100]`? That's no different to accidentally writing `new int[1]`. The best approach is to avoid using C-style arrays, and use container-classes. – Oliver Charlesworth Nov 09 '10 at 12:37
  • @Oli Charlesworth: new int[size]; size wrongly computed as zero at runtime due to some logic. This is the bug i am talking about. – bjskishore123 Nov 09 '10 at 12:40
  • @bjskishore123: That's really the same thing. What if the runtime error wrongly computed `size` as `1`? – Oliver Charlesworth Nov 09 '10 at 12:50
  • @Oil Charlesworth: +1, Agree. – bjskishore123 Nov 09 '10 at 12:55
  • @bjskishore123: One way to catch that bug is `assert(size > 0)`, before you do `new int[size]` – Steve Jessop Nov 09 '10 at 13:29
  • @Steve: Yes, Exactly what i am gonna do for debug builds(assert). I hope its not required for release builds. – bjskishore123 Nov 09 '10 at 16:14
5

Long time ago, before using exceptions, the malloc function returned a NULL pointer if the allocation failed.

If allocating zero bytes would also return a NULL pointer, it would be hard to make the distinction between a failed allocation and a succeeding-zero-bytes allocation.

On the other hand if the allocation of zero bytes would return a non-NULL pointer, you end up with a situation in which two different allocations of zero bytes can have the same pointer.

Therefore, to keep things simple, the malloc function of zero bytes allocates 1 byte.

Patrick
  • 22,097
  • 9
  • 57
  • 125
  • malloc(0) not necessarily allocates 1 byte, it may return null (http://www.opengroup.org/onlinepubs/009695399/functions/malloc.html). – vitaut Nov 09 '10 at 12:21
  • @vitaut: I think there's a difference between theory and practice. In theory it could return NULL. In practice every (or most) compiler vendor realized that it would be annoying to return a NULL pointer, and therefore always allocated a minimum of 1 byte. – Patrick Nov 09 '10 at 12:51
5

3.7.3.1/2:

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

Compare dynamically allocated array to std::vector for example. You can have a vector of size 0, so why not allow the same for the array? And it is always an error to access past the end of the array whether its size is 0 or not.

vitaut
  • 37,224
  • 19
  • 144
  • 248
  • Agree. But for vector, size() can be checked before use. But array is deadly. – bjskishore123 Nov 09 '10 at 12:30
  • 1
    @bjskishore123: You have to store the size of the dynamic array somewhere, don't you? The only difference is that vector does it for you. – vitaut Nov 09 '10 at 12:47
  • +1, Fine, May be i can think of adding check like computedSize > 0, then only use the pointer. – bjskishore123 Nov 09 '10 at 12:53
  • 1
    +1: It also makes it simpler to allocate an array of n items and iterate over them, with this rule 0 is a valid number for n and doesn't need special handling. – Binary Worrier Nov 09 '10 at 13:03
3

The same can be said for int[N] where N>0:

Because if size to be allocated is calculated at run time and if programmer assumes its allocated properly and tries to write something past end of that memory, ends up corrupting memory !!! and Crash may happen some where else in the code.

Abyx
  • 10,859
  • 4
  • 36
  • 74
2

Zero sized array allocation is covered in the ISO C++ Standard under 5.3.4, paragrahp 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.

This makes code that performs dnaymic array allocation easier.

In general: If someone calls a function and asks it to return an array with n (0 in your case) elements, the code shouldn't be trying to read the returned array past the n-nth element anyway.

So, I don't really see the catastrophic failure, since the code would have been faulty to begin with for any n.

As you say:

Because if size to be allocated is calculated at run time and if programmer assumes its allocated properly

The calculated size would be "0", if he tries to access more than his calculated size then, well.. I am repeating myself ;)

lx.
  • 2,277
  • 1
  • 23
  • 32