4

I was wondering how delete[] knows the size of a dynamically allocated array, and I found this question (and also this question on a Microsoft forum, but the answer is similar). Turns out the answer is

This is usually stored in a "head" segment just before the memory that you get allocated.

Thus the exact details are implementation specific.
Under that answer one of the comments asks why this quite useful piece of information is not available to the programmers, forcing us to pass around variables denoting the size. The answer the comment got is

Forcing the allocator to store the requested size (so that you wouldn't need to pass the array size yourself) might be a small encumbrance, but it could have performance impacts on conceivable allocator designs

To me, that isn't very convincing considering the size should be accessible to delete[] anyhow.

My question: is it possible (for a programmer) to retrieve the size somehow?

I am aware that there's a Microsoft special way (as it was noted in the aforementioned MS forum), but I am after something standardized.

You can use the Microsoft-specific function _msize() to get the size of a dynamically allocated array from the pointer, even when it is passed to another function than the one which did the allocation.

Aykhan Hagverdili
  • 28,141
  • 6
  • 41
  • 93
  • 5
    Just use `std::vector` and don't worry about it. – NathanOliver Dec 11 '18 at 13:46
  • 4
    @NathanOliver While I very approve this recommendation, it has nothing to do with the question itself. – Zereges Dec 11 '18 at 13:47
  • The question is well beyond C++'s scope, which demands a platform-agnostic memory model, where a head section is not specify. For platform-dependent solutions, name/tag the platform and be as specific as possible. – YiFei Dec 11 '18 at 13:50
  • @YiFei my point is, as the information has to be stored somewhere anyway, there is no reason for it to inaccessible – Aykhan Hagverdili Dec 11 '18 at 13:58
  • 4
    Sure, it could be accessible but they decided to not demand this. There are multiple ways to implement this, like not storing the size of the array at all since it can be reverse-engineered from the size of the heap block. And to compact this info for small heap blocks, where it matters. Giving the library implementer the freedom to it the way he wanted was intentional. That your CRT has a back-door is not unusual, have a look. – Hans Passant Dec 11 '18 at 14:03
  • @Zereges it has everything to do with this question. You only need `delete[]` if you call `new[]`, and if you replace all instances of `new[]` with suitable uses of `std::vector`s, your get a helpful handle to both the logical size and the allocation size of the "dynamic array" – Caleth Dec 11 '18 at 14:08
  • "I am after something standardized.". It is not standardized. And actually, memory allocators do differ. So this cannot be done in a platform-independent way. If you want to control memory better, use your own allocator, and maybe avoid using `new` altogether (except one place: to construct objects with placement new). – geza Dec 11 '18 at 15:06
  • It does not have to be stored, there are other possible strategies. For example, a pointer to an array of object followed by a special token terminator mark. The other strategies may not be as efficient; but they could offer other benefits or tradeoffs, such as detecting memory leaks or mix-up of `delete` for `delete[]` or for `free`. – Eljay Dec 11 '18 at 15:30
  • @Eljay So the size isn't necessarily stored somewhere? Okay now, I think your comment combined with Hans's comment answers my question, thanks. – Aykhan Hagverdili Dec 11 '18 at 17:00
  • 1
    @Caleth There are situations, where `std::vector` (or other STL facilities) are not acceptable, such as school and self studying, and finding out the design reason why size of memory block allocated via `new[]` isn't accessible to the programmer is useful in this case. – Zereges Dec 11 '18 at 22:45
  • @Ayxan Think about an allocation for one byte and an allocation for two bytes. Almost any sensible implementation is going to return a block of the same actual internal allocated size in that case. So whether one or two bytes was asked for need not be stored. – David Schwartz Dec 12 '18 at 16:27
  • @DavidSchwartz that makes sense, but would storing the size have any detrimental effects? Does the cost of storing the size justify not standardizing? – Aykhan Hagverdili Dec 12 '18 at 16:32
  • @Ayxan The problem is that it's hard to imagine the many possible allocator designs. Since this feature is almost never needed and very easy to implement if you do need it, it makes no sense to require every allocator to always provide it. – David Schwartz Dec 12 '18 at 18:41
  • @DavidSchwartz Clear now, thank you – Aykhan Hagverdili Dec 12 '18 at 19:26

2 Answers2

3

If you work with open source libraries, then yes you can! Just look up the source, figure out how and go for it.

It is still a bad idea though, since there are no guarantees: the implementation could change at any moment and is not guaranteed to be portable even between Unix and Linux. The number could also be too large, since it might be advantagous to allocate more, for example to align. It is also unnecessary: when you new a space you know the size. You could just pass it, or store it in some place which you control. This is not worse than looking it up trough the implementation of malloc.

Cheiron
  • 3,620
  • 4
  • 32
  • 63
  • 2
    Actually, I am looking for something portable, and if it over allocates, we could have used that for our advantage too. My point is as the information has to be stored somewhere anyway, there is no reason for it to inaccessible – Aykhan Hagverdili Dec 11 '18 at 14:01
  • @Ayxan • it is not accessible as per the C++ standard, in part because the C++ standard does not require that such a thing exist. Accessing it would have to be on a platform-by-platform basis, and would not be portable. – Eljay Dec 11 '18 at 16:25
2

My conclusion is:
The size of the array might be stored in memory, but it is not necessarily the case; there are other ways of achieving the desired behavior, each with its own trade-offs and ISO specifically gives the compiler writers the freedom to choose so that they can optimize it as much as necessary.
That is to say, there is not a single, standardized way of getting the size of a dynamically allocated array as of now.

Aykhan Hagverdili
  • 28,141
  • 6
  • 41
  • 93
  • Any update on this? It's an interesting problem. Is this behaviour due to pointers? Is it because it doesn't matter what the size of the array is as long as you're passing a pointer to its beginning? What happens if I increment the pointer past the memory I've allocated? – Connor Feb 24 '23 at 12:18
  • 1
    @Connor It is because the way the size of the dynamically allocated memory stored (if at all) is different in different implementations. I don't know what you are trying to do, but 99% of the time you can just use `std::vector` and that always knows its size. – Aykhan Hagverdili Feb 24 '23 at 13:31
  • Interesting, I'm working in C, does it have these `::` style operators? – Connor Feb 24 '23 at 14:40
  • 1
    @Connor This is specifically about C++. `std` is a namespace in C++. And `vector` is a class template, which is basically an implementation of a runtime-sized array. For example, if you want a runtime-sized array of integers, you would do `std::vector myArr;`. If you're using C, that's a separate discussion. – Aykhan Hagverdili Feb 24 '23 at 14:42