27

Why is it not possible to get the length of a buffer allocated in this fashion.

AType * pArr = new AType[nVariable];

When the same array is deallocated

delete [] pArr;

the runtime must know how much to deallocate. Is there any means to access the length before deleting the array. If no, why no such API is provided that will fetch the length?

iammilind
  • 68,093
  • 33
  • 169
  • 336
Ram
  • 3,045
  • 3
  • 27
  • 42
  • Best way is to use, `std::vector pArr(nVariable);`. This internally allocates using dynamic allocation and you have `.size()` always handy. – iammilind Sep 27 '12 at 08:42
  • 1
    [C++ FAQ entry on this.](http://www.parashift.com/c++-faq-lite/num-elems-in-new-array.html) – jrok Sep 27 '12 at 10:46

8 Answers8

9

Is there any means to access the length before deleting the array?

No. there is no way to determine that.
The standard does not require the implementation to remember and provide the specifics of the number of elements requested through new.
The implementation may simply insert specific bit patterns at end of allocated memory blocks instead of remembering the number of elements, and might simply lookup for the pattern while freeing the memory.
In short it is solely an imlpementation detail.


On a side note, There are 2 options to practically overcome this problem:

  1. You can simple use a std::vector which provides you member functions like size() or
  2. You can simply do the bookkeeping yourself.

new atleast allocates enough memory as much as you requested.
You already know how much memory you requested so you can calculate the length easily. You can find size of each item using sizeof.

Total memory requested / Memory required for 1 item = No of Items
Alok Save
  • 202,538
  • 53
  • 430
  • 533
  • 4
    I didn't downvoted you, but I think the problem is that he's asking why the standard doesn't provide that, and you say that it is that way because the standard says that. He's asking for a rationale, not for a solution of a concrete problem. – akappa Sep 27 '12 at 11:07
  • @akappa: My answer states the rationale, there can be effective/better ways in which a implementation can keep track of allocated memory, and hence the standard doesn't force the implementations to do so in a particular way.In fact the answer even states one of such ways.Since you say this is not rationale please enlighten me on How/why do you think this is not a rationale? – Alok Save Sep 28 '12 at 10:06
  • 1
    "Inserting patterns" does not prevent you to report how long the chunk is: it would just be a non-constant query. I would say that there could be settings in which the `C++ RTS` might not know **in any way** that information because (say) it is kept by the OS and he's not willing to say that to you (but it could expose a function that lets you delete chunks of memory and apply a function to the memory being deleted, for ex calling dtors). In short, this is a case where the C++ RTS relies on lower-level RTS, so the standard enforces the lowest restrictions to implementations to keep costs down. – akappa Sep 28 '12 at 10:46
6

The runtime DOES know how much was allocated. However such details are compiler specific so you don't have any cross platform way to handle it.

If you would like the same functionality and be able to track the size you could use a std::vector as follows:

std::vector< AType > pArr( nVariable );

This has the added advantage of using RAII as well.

Goz
  • 61,365
  • 24
  • 124
  • 204
  • I agree that the implementation is compiler specific. But what stops the standard from asking C++ vendors to expose an API such as the one below. size_t array_sizeof(void const * pHead); – Ram Sep 27 '12 at 18:54
  • @Ram: I don't know what stops the standard asking for that as many run times do allow it. There may be some way of implementing allocations for which it can't be done and thats the reason for not forcing it to be exposed. I can't think, however, of an allocation pattern for which you couldn't do it though ... – Goz Sep 28 '12 at 08:49
  • @Ram: Personally I always use vectors instead of dynamic allocation for the benefits of RAII, copy semantics and size tracking. – Goz Sep 28 '12 at 08:50
3

The delete operator doesn't need to know the size to free the allocated memory, just like the free system call doesn't. This is because that problem is left to the operating system and not the compilers runtime system.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • 1
    Not really, delete operation and the free library function need to know this. I think many implementations do not return heap allocated memory to the OS, but reuse it, and even if they do return memory, there is no 1:1 mapping between free/delete invocation and a system call that returns memory (this is because OS usually won't allow you to return memory in small chunks but in multiplies of a page size) . – Jan Wrobel Sep 27 '12 at 08:50
  • 1
    at least for non-POD datatypes the runtime HAS to know it, since it must call the dtors. For POD datatypes it is safe to say that the C++ RTS may or may not know how much space it has been allocated, since bare memory handling is out of the standard. – akappa Sep 27 '12 at 10:42
3

The runtime must deallocate the same amount as it allocated, and it does keep track of this in some manner (usually very indirectly). But there's no reliable way of getting from amount allocated to number of elements: the amount allocated cannot be less than the number of elements times the size of each element, but it will often be more. Alignment considerations, for example, mean that new char[5] and new char[8] will often allocate the same amount of memory, and there are various allocation strategies which can cause significantly more memory to be allocated that what is strictly necessary.

James Kanze
  • 150,581
  • 18
  • 184
  • 329
2

No, not really. At least not in a platform-independent, defined way.

Most implementations store the size of a dynamically allocated array before the actual array though.

Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
  • 3
    Really. The ones I've seen don't. – James Kanze Sep 27 '12 at 10:09
  • @JamesKanze MSVS surely does. – Luchian Grigore Sep 27 '12 at 10:09
  • I just tried it with VC10. If I do `new char[10]`, the `size_t` immediately before the returned pointer contains `917978`. (With g++, it contains `17`, which may actually be related to the amount of memory allocated, since alignment considerations will require rounding the amount up to the next multiple of 8.) – James Kanze Sep 27 '12 at 10:44
1

There is no portable way in C++ to get the size of a dynamically allocated array from the raw pointer.

Under MSVC and WIN32 you can get the size of the allocated block with the _msize(void*) function.

see https://msdn.microsoft.com/en-us/library/z2s077bc.aspx for further details.

vre
  • 6,041
  • 1
  • 25
  • 39
1

I use this "dirty" method, only for debugging purpose:

T *p = new T[count];
size_t size = (char*)&(p[count]) - (char*)p;

This gives the size of real data but not any extra size that could has been allocated by the compiler.

For already aligned types T, it is equal to:

size_t size = sizeof(T) * count;

Of course this doesn't works if you don't know the count of items in array.

stegemma
  • 21
  • 2
0

why not a bit of extra info like this:

template <typename T> class AType
{
public:

    AType(size_t s) : data(0)
    {
        a_size = s;
        data = new T[s];
    }
    ~AType() {
        if (data != nullptr)
            delete [] data;
    }

    size_t getSize() const
    {
        return a_size * sizeof(T);
    }

private:
    size_t a_size;
    T* data;
};
Ilian Zapryanov
  • 1,132
  • 2
  • 16
  • 28