zero dynamic memory allocation

So today I was reviewing teacher code that lets student input the number of blocks of memory to allocate, but the student can input zero. It seems to allocate the memory space, but why is this even allowed?

Best to check against null address and zero memory allocation if this is the case then.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include<iostream>
#include<algorithm>

using namespace std;

int main()
{
	int* pInt = new(nothrow) int[0];

	cout << pInt << endl;



	if (pInt)
	{
		cout << "DID ALLOCATE" << endl;

		cout << *pInt << endl;
		delete[] pInt;
	}
	else
	{
		cout << "DID NOT ALLOCATE" << endl;
	}

		
	cout << "BLAH BLAH" << endl;
	

	return 0;
I think the offical C standard does not allow zero-size arrays, but many C/C++ compilers support it anyway.

For example, The GNU C compiler says this:
https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html

When it comes to dynamic memory allocation, malloc() officially supports zero-size allocations. Calling malloc(0) will either return a NULL pointer or a special "unique" pointer value. In both cases, it is guaranteed that the returned pointer can safely be passed to free().

Another important thing to note is that, in C++, the operator new T[n] actually allocates a memory block that is slightly larger than n times sizeof(T). That is because it allocates a little extra space where n (i.e. the length of the array) is stored. The pointer returned by new T[n] is pointing to the first element of the array, not to the beginning of the allocated memory block – because the value n is "secretly" stored right in front of the first element (i.e. at the very beginning of the memory block). It is done this way, because the delete[] operator later needs a way to figure out the actual length of the array, so that it can iterate over the array and call the destructor of each element!

That is also the reason why the delete and delete[] operators can not be used interchanagbly: The former simply destroys a sinlge object; the latter destroys and array and thus expectecs/requires the length of the array to be stored in front of the given given pointer.

If you do new T[0], it probably still allocates the extra space for n, which would hold a zero in this case, so that delete[] can work correctly.


In order to call the destructors of the array elements when delete[] is called, the implementation must know the size of array to which p points at deletion time. Bearing in mind that p is a pointer, and carries no array size information in its type, this information would not in general be available unless the implementation somehow stores it when new[] is invoked.

The most common approach is to allocate a small amount of extra memory (a header) before the start of the array and store the size in it. When invoking delete[] p, the implementation then just needs to walk back a fixed amount from the passed-in pointer to read the size.

https://codeql.github.com/codeql-query-help/cpp/cpp-new-array-delete-mismatch/
Last edited on
Using new to create an array of size zero is fine.

When the value of the expression is zero, the allocation function is called to allocate an array with no elements.
https://eel.is/c++draft/expr.new#8.sentence-4

The intent is to have operator new() implementable by calling std​::​malloc() or std​::​calloc(), so the rules are substantially the same.
C++ differs from C in requiring a zero request to return a non-null pointer.
https://eel.is/c++draft/basic.stc.dynamic.allocation#footnote-24

This is when the allocation succeeds. Even if the array size is zero the allocation could still fail, giving you a null pointer if you use nothrow.
Last edited on
And just to be clear, line 18 leads to undefined behaviour. You're essentially accessing an array element out of bounds.
Well it was written by a teacher. I need say no more.....
Registered users can post here. Sign in or register to post.