In all my classes I've been told an array does not know it's size.
1 2
char* a = newchar[5];
char b = a[20];
Uh oh, arrays don't know their size and nothing will stop you from accessing past the end of their memory chunk. But, delete[] a; knows exactly what chunk of memory to free, without being handed a size. So somewhere the operating system knows the size of an array but just doesn't do range checks.
I asked some people smarter than myself about it and was told it's different on different systems, but most of the time there is a table the operating system stores addresses at, and the OS searches the table for the start and end location of an array when delete is called to free the memory.
So finally my question is, can I get to these values somehow? I'm not looking for anything portable, just an example of how it might be done in one case. And if not an example maybe somewhere to read about this kind of stuff.
Note that a is not an array. It's a pointer to the first element in an array. A pointer only contains a memory address and it could point to any object, not just objects in arrays.
You can get the length from an array if it's of an array type.
1 2
int arr[5];
std::cout << "Length of array: " << (sizeof(arr) / sizeof(arr[0])) << std::endl;
This is thanks to the type system. The length of the array is embeded in the array type.
When you go from array to pointer the length information is lost. There is no way you can convert a pointer back to array type.
Peter87, there is no way to get back the size of dynamically allocated memory as it's not known at compile time. I believe that's what OP is talking about. You instead have to pass around the size via a separate variable.
I believe (read this somewhere) that dynamically allocated arrays reserve a byte or so of memory in front of the 0th element which says how many elements are in the array. This could be implementation specific, though.
From our viewpoint the array form of delete knows only two things: start address and size of one object. Ok, make it three: how to call the destructor of such object.
Obviously the deletion must have access to the block size in order to mark the block deallocated. However, that is not all. The operation will call the destructor on each object within the block.
Similarly, C has realloc(). It knows. It can copy.
However, the languages don't offer any size query method for us.
Heaps are usually implemented using boundary tags. A boundary tag is typically a word (implementation specific) before and after a memory area. The sign bit indicates if the area is available. The remaining bits are the size of the memory area. When an area is allocated, the area is divided into used and unused portions. The front boundary tag is always at the address of the area minus the size of the boundary tag. The ending tag can always be found by adding the size of absolute value of the boundary to the address of the starting tag. When an area is released, the sign of the boundary tags is changed. Coalescing unused areas is simply a matter of checking if the area being returned is adjacent to an unused area (before or after). Boundary tags were first described by Knuth in 1973. http://homepage.cs.uiowa.edu/~jones/syssoft/fall00/notes/14alloc.html