Alex Rivera | Logout

Can you obtain the size of an array allocated with new T[]?

Asked 2008-10-13T14:50:36.593
64

This question was inspired by a similar question: How does delete[] “know” the size of the operand array?

My question is a little different: Is there any way to determine the size of a C++ array programmatically? And if not, why? Every function I've seen that takes an array also requires an integer parameter to give it the size. But as the linked question pointed out, delete[] must know the size of the memory to be deallocated.

Consider this C++ code:

int* arr = new int[256];
printf("Size of arr: %d\n", sizeof(arr));

This prints "Size of arr: 4", which is just the size of the pointer. It would be nice to have some function which prints 256, but I don't think one exists in C++. (Again, part of the question is why it doesn't exist.)

Clarification: I know that if I declared the array on the stack instead of the heap (i.e. "int arr[256];") that the sizeof operator would return 1024 (array length * sizeof(int)).

Edit
Report

5 Answers

71

delete [] does know the size that was allocated. However, that knowledge resides in the runtime or in the operating system's memory manager, meaning that it is not available to the compiler during compilation. And sizeof() is not a real function, it is actually evaluated to a constant by the compiler, which is something it cannot do for dynamically allocated arrays, whose size is not known during compilation.

Also, consider this example:


int *arr = new int[256];
int *p = &arr[100];
printf("Size: %d\n", sizeof(p));

How would the compiler know what the size of p is? The root of the problem is that arrays in C and C++ are not first-class objects. They decay to pointers, and there is no way for the compiler or the program itself to know whether a pointer points to the beginning of a chunk of memory allocated by new, or to a single object, or to some place in the middle of a chunk of memory allocated by new.

One reason for this is that C and C++ leave memory management to the programmer and to the operating system, which is also why they do not have garbage collection. Implementation of new and delete is not part of the C++ standard, because C++ is meant to be used on a variety of platforms, which may manage their memory in very different ways. It may be possible to let C++ keep track of all the allocated arrays and their sizes if you are writing a word processor for a windows box running on the latest Intel CPU, but it may be completely infeasible when you are writing an embedded system running on a DSP.

answered 2008-10-13T15:03:26.007
3

Some magic:

template <typename T, size_t S>
inline
size_t array_size(const T (&v)[S]) 
{ 
    return S; 
}

And this is how we do it in C++11:

template<typename T, size_t S>
constexpr 
auto array_size(const T (&)[S]) -> size_t
{ 
    return S; 
}
answered 2013-06-09T22:29:27.630
2

That's because your variable arr is only a pointer. It holds the address of a particular location in memory, without knowing anything about it. You declare it to be int*, which gives the compiler some indication of what to do when you increment the pointer. Other than that, you could be pointing into the beginning or the end of the array or into the stack or into invalid memory. But I agree with you, not being able to call sizeof is very annoying :)

QuantumPete

answered 2008-10-13T14:56:22.527
2

There is no portable way of determining the size of a dynamically-allocated array in C++ given only its pointer. C++ is made to be very flexible and to give power to the user. For example, the standard does not define how memory allocators must work, e.g. by adding a required size header. Not requiring a header allows for a lot more flexibility.

As one example, consider a string implemented as a char * array. It's common to use pointers into the middle of the array to pick out substrings. As an example, see the strtok function in the standard C library. If some header were required to be embedded just before each array, you'd need to trash portions of the array before the substring.

An alternative way to handle the headers would be to have array headers in one block of memory and have them point to the raw array memory elsewhere. In many situations, this would require two pointer lookups for each reference, which would be a big drag on performance. There are ways of overcoming these deficiencies, but they add complexity and reduce implementation flexibility.

The std::vector template is my favorite way of keeping the size of an array bound to the array itself.

C is portable assembly language with a better syntax.

answered 2008-10-13T15:06:36.903
1

Unfortunately, this is not possible. In C and C++, it is the responsibility of the programmer to remember of the length of an array since array length is not stored anywhere. Delete[] and free() does remember the size of the allocated block but they might allocate more memory than requested so their internal data structures storing the sizes of allocated memory blocks might not give you the exact size of the your array.

Note that C++ STL vectors, which are basically arrays wrapped in a class with some helper functions, do store the length of the array so if you really need this functionality, you could just use vectors.

answered 2008-10-13T15:06:25.313

Your Answer