+1 Very interesting question - although I'm not sure how much it matters in real code.
–
ZifreJul 6 '09 at 13:46

12

@Zifre: I'm asking for curiosity, but it might matter in real world, e.g. when size of allocated memory blocks is calculated in some way, and the result of the calculation might be zero, then there is no direct need to add exceptions to not allocate zero sized blocks.. Because they should be allocated and deleted without errors (if only the zero sized block is not dereferenced). So generally this gives wider abstraction of what a memory block is.
–
anonJul 6 '09 at 13:59

It's only tangentially related - so I'm commenting here - but C++ in many ways ensures that distinct objects have unique addresses...even if they don't explicitly require storage. A related experiment would be to check the size of an empty struct. Or an array of that struct.
–
Drew DormannJul 6 '09 at 15:47

1

To elaborate on Shmoopty's comment: Especially when programming with templates (e.g. policy class templates like std::allocator), it is common in C++ to have zero-sized objects. Generic code may need to dynamically allocate such objects and use pointers to them to compare object identity. This is why operator new() returns unique pointers for zero-sized requests. While arguably less important/common, the same reasoning applies to array allocation and operator new[]().
–
Trevor RobinsonJan 13 '10 at 20:46

4 Answers
4

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.

From 3.7.3.1/2

The effect of dereferencing a pointer returned as a request for zero size is undefined.

Also

Even if the size of the space requested [by new] is zero, the request can fail.

That means you can do it, but you can not legally (in a well defined manner across all platforms) dereference the memory that you get - you can only pass it to array delete - and you should delete it.

Here is an interesting foot-note (i.e not a normative part of the standard, but included for expository purposes) attached to the sentence from 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.]

I get a memory leak if I don't delete. Is it expected? At least I didn't expect.
–
EralpBMar 10 '14 at 13:46

2

@EralpB: on the contrary, even if your request is zero, this allocation happens on the Heap, where one request implies several book keeping operations, like allocating and initializing heap guards before and after the zone given by the allocator, insertion into freelists or other complex horrible structures. Freeing it means doing the backward bookkeeping.
–
v.oddouJun 13 '14 at 12:18

Do you have a citation for this? We all know that int ar[0]; is illegal why is new OK?
–
MottiJul 6 '09 at 13:47

See Faisal's answer.
–
anonJul 6 '09 at 13:48

2

It's interesting that C++ isn't so strong with forbidding zero sized objects. Think of the empty base class optimization: Here too, an empty base class sub-object may have size zero. In contrast, the C Standard makes a strong effort to ensure there never are zero sized objects created: In defining malloc(0) it says the effect is of running malloc with some non-zero argument, for example. And in struct { ...; T n[]; }; when there is no space allocated for the array (FAM), it says it behaves as if "n" has one element. (In both cases, using the object in any way is UB, like x.n[0])
–
Johannes Schaub - litbJul 6 '09 at 16:25

Regarding malloc, you are right - it is implementation defined. This is often seen as a misfeature.
–
anonJul 6 '09 at 13:49

I suppose an interesting question is: can the nothrow version of new return NULL if given a size of 0?
–
Evan TeranJul 6 '09 at 13:52

1

The semantics of new and malloc are not linked in any way, at least by the standard.
–
anonJul 6 '09 at 13:53

not saying they are... was specifically asking about the nothrow version of new.
–
Evan TeranJul 6 '09 at 13:55

@Evan - the nothrow version of new returns null only if the request fails - not just if the request size is 0 @Neil - not normatively linked - but linked by intent (i.e. operator new may be implemented in terms of malloc but not the other way around) - see the footnote i included in my answer
–
Faisal ValiJul 6 '09 at 14:07