Finding size of dynamically allocated array - c++

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?

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:
You can simple use a std::vector which provides you member functions like size() or
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

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.

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.

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.

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.

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.

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.

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;
};

Related

Allocating Sufficient Memory for a Known Number of Structs

First time implementing a graph where the total number of nodes is known when the constructor is called and performance is the highest priority.
Never allocated memory before, so the process is a little hazy.
The number of nodes required is (n*(n+1))/2 where n is the length of the string passed to the constructor.
#include <string>
struct ColorNode {
ColorNode* lParent;
ColorNode* rParent;
char color;
};
class ParentGraph {
std::string base;
int len, nodes;
ParentGraph(std::string b): base(b) {
len = base.length();
nodes = (len * (len + 1)) / 2;
// how to allocate enough memory for number of copies of "ColorNode" equal to "nodes"?
}
};
What is the best practice for allocating memory in this instance?
Will allocating the memory beforehand make a significant difference in performance?
It may turn out that an array or vector is a better choice, but really need the practice in both data structures and memory allocation.
Thanks for the consideration.
use
std::vector<ColorNode> nodes;
life will be very simple after that.
You can be helpful to std::vector if you know the size you want
auto nodes = std::vector<ColorNode>(size);
This will allocate a contiguous array on the heap for you, manage its growth, allocation, deallocation etc.
You will basically get the same in memory structure if you do new ColorNode[size] (or even malloc(....) if some evil person tried to persuade you that raw malloc will be faster). But you have to do all the nasty management yourself.
You only need to diverge from this advice if you have too many objects to fit into one contiguous memory block. If thats the case say so

Is there a way to print the amount of heap memory an object has allocated?

In a running program, how can I track/print the amount of heap memory an object has allocated?
For example:
#include <iostream>
#include <vector>
int main(){
std::vector<int> v;
std::cout << heap_sizeof(v) << '\n';
for (int i = 0; i < 1000; ++i){
v.push_back(0);
}
std::cout << heap_sizeof(v) << '\n';
}
Is there an implementation that could substitute heap_sizeof()?
With everything as it's designed out of the box, no, that's not possible. You do have a couple of options for doing that on your own though.
If you need this exclusively for standard containers, you can implement an allocator that tracks the memory that's been allocated (and not freed) via that allocator.
If you want this capability for everything allocated via new (whether a container or not) you can provide your own implementation of operator new on a global and/or class-specific basis, and have it (for example) build an unordered map from pointers to block sizes to tell you the size of any block it's allocated (and with that, you'll have to provide a function to retrieve that size). Depending on the platform, this might also be implemented using platform-specific functions. For example, when you're building for Microsoft's compiler (well, library, really) your implementation of operator new wouldn't have to do anything special at all, and the function to retrieve a block's size would look something like this:
size_t block_size(void const *block) {
return _msize(block);
}
Yet another possibility would be to increase the allocation size of each requested block by the size of an integer large enough to hold the size. In this case, you'd allocate a bigger chunk of data than the user requested, and store the size of that block at the beginning of the block that was returned. When the user requests the size of a block, you take the correct (negative) offset from the pointer they pass, and return the value you stored there.
First, v is allocated on the stack, not on the heap.
To get the total amount of space used by it, I suggest using this function: (Found on this article, and modified a bit)
template <typename T>
size_t areaof (const vector<T>& x)
{
return sizeof (vector<T>) + x.capacity () * sizeof (T);
}
If you want not to count the size of the std::vector object itself, the delete the part with sizeof:
template <typename T>
size_t heap_sizeof (const vector<T>& x)
{
return x.capacity () * sizeof (T);
}
If you are not concerned with accounting for what each object allocates and are more concerned with how much memory has been allocated/freed between to point in time, you can use the malloc statistics functions. Each malloc has its own version. On linux you can usemallocinfo().

How can I know the allocated memory size of a std::vector?

I understand that we can use size() function to obtain the vector size, for example:
std::vector<in> abc;
abc.resize(3);
abc.size();
The my question is how can I know the memory size of a vector? Take an example:
std::vector<int> abc;
abc.reserve(7);
//the size of memory that has been allocated for abc
You use the member function capacity() to obtain the allocated capacity
std::vector<int> abc;
abc.reserve(7);
std::cout << abc.capacity() << std::endl;
To get the memory allocated by in bytes, You can do:
sizeof(int) * abc.capacity();
This is given, that you know your value_type is int. If you don't
sizeof(decltype(abc.back())) * abc.capacity();
The real answer is that you can't. Others have suggested ways that will often work, but you can't depend on capacity reflecting in any way the actual memory allocated.
For one thing, the heap will often allocate more memory than was requested. This has to do with optimizations against fragmenting, etc... vector has no way of knowing how much memory was actually allocated, only what it requested.
So capacity at best gives you a very rough estimate.
Use the capacity member function - http://en.cppreference.com/w/cpp/container/vector/capacity
There are strong statements on the memory being contiguous, and so the size is
sizeof( abc[0] ) * abc.capacity();
or
( (char*)(&abc[1]) - (char*)(&abc[0] ) ) * abc.capacity();
Since std::vector can store complex objects (such as std::string), which have their internal memory management and may allocate additional memory, determining the total memory usage can be hard.
For a vector containing simple objects such as int, the suggested solution using capacity and sizeof will work though.

Pointer to an array get size C++

int * a;
a = new int[10];
cout << sizeof(a)/sizeof(int);
if i would use a normal array the answer would be 10,
alas, the lucky number printed was 1, because sizeof(int) is 4 and iszeof(*int) is 4 too. How do i owercome this? In my case keeping size in memory is a complicated option. How do i get size using code?
My best guess would be to iterate through an array and search for it's end, and the end is 0, right? Any suggestions?
--edit
well, what i fear about vectors is that it will reallocate while pushing back, well you got the point, i can jus allocate the memory. Hoever i cant change the stucture, the whole code is releevant. Thanks for the answers, i see there's no way around, so ill just look for a way to store the size in memory.
what i asked whas not what kind of structure to use.
Simple.
Use std::vector<int> Or std::array<int, N> (where N is a compile-time constant).
If you know the size of your array at compile time, and it doens't need to grow at runtime, then use std::array. Else use std::vector.
These are called sequence-container classes which define a member function called size() which returns the number of elements in the container. You can use that whenever you need to know the size. :-)
Read the documentation:
std::array with example
std::vector with example
When you use std::vector, you should consider using reserve() if you've some vague idea of the number of elements the container is going to hold. That will give you performance benefit.
If you worry about performance of std::vector vs raw-arrays, then read the accepted answer here:
Is std::vector so much slower than plain arrays?
It explains why the code in the question is slow, which has nothing to do with std::vector itself, rather its incorrect usage.
If you cannot use either of them, and are forced to use int*, then I would suggest these two alternatives. Choose whatever suits your need.
struct array
{
int *elements; //elements
size_t size; //number of elements
};
That is self-explanatory.
The second one is this: allocate memory for one more element and store the size in the first element as:
int N = howManyElements();
int *array = int new[N+1]; //allocate memory for size storage also!
array[0] = N; //store N in the first element!
//your code : iterate i=1 to i<=N
//must delete it once done
delete []array;
sizeof(a) is going to be the size of the pointer, not the size of the allocated array.
There is no way to get the size of the array after you've allocated it. The sizeof operator has to be able to be evaluated at compile time.
How would the compiler know how big the array was in this function?
void foo(int size)
{
int * a;
a = new int[size];
cout << sizeof(a)/sizeof(int);
delete[] a;
}
It couldn't. So it's not possible for the sizeof operator to return the size of an allocated array. And, in fact, there is no reliable way to get the size of an array you've allocated with new. Let me repeat this there is no reliable way to get the size of an array you've allocated with new. You have to store the size someplace.
Luckily, this problem has already been solved for you, and it's guaranteed to be there in any implementation of C++. If you want a nice array that stores the size along with the array, use ::std::vector. Particularly if you're using new to allocate your array.
#include <vector>
void foo(int size)
{
::std::vector<int> a(size);
cout << a.size();
}
There you go. Notice how you no longer have to remember to delete it. As a further note, using ::std::vector in this way has no performance penalty over using new in the way you were using it.
If you are unable to use std::vector and std::array as you have stated, than your only remaning option is to keep track of the size of the array yourself.
I still suspect that your reasons for avoiding std::vector are misguided. Even for performance monitoring software, intelligent uses of vector are reasonable. If you are concerned about resizing you can preallocate the vector to be reasonably large.

How to expand an array dynamically in C++? {like in vector }

Lets say, i have
int *p;
p = new int[5];
for(int i=0;i<5;i++)
*(p+i)=i;
Now I want to add a 6th element to the array. How do I do it?
You have to reallocate the array and copy the data:
int *p;
p = new int[5];
for(int i=0;i<5;i++)
*(p+i)=i;
// realloc
int* temp = new int[6];
std::copy(p, p + 5, temp); // Suggested by comments from Nick and Bojan
delete [] p;
p = temp;
You cannot. You must use a dynamic container, such as an STL vector, for this. Or else you can make another array that is larger, and then copy the data from your first array into it.
The reason is that an array represents a contiguous region in memory. For your example above, let us say that p points to address 0x1000, and the the five ints correspond to twenty bytes, so the array ends at the boundary of 0x1014. The compiler is free to place other variables in the memory starting at 0x1014; for example, int i might occupy 0x1014..0x1018. If you then extended the array so that it occupied four more bytes, what would happen?
If you allocate the initial buffer using malloc you can use realloc to resize the buffer. You shouldn't use realloc to resize a new-ed buffer.
int * array = (int*)malloc(sizeof(int) * arrayLength);
array = (int*)realloc(array, sizeof(int) * newLength);
However, this is a C-ish way to do things. You should consider using vector.
Why don't you look in the sources how vector does that? You can see the implementation of this mechanism right in the folder your C++ include files reside!
Here's what it does on gcc 4.3.2:
Allocate a new contiguous chunk of memory with use of the vector's allocator (you remember that vector is vector<Type, Allocator = new_allocator>?). The default allocator calls operator new() (not just new!) to allocate this chunk, letting himself thereby not to mess with new[]/delete[] stuff;
Copy the contents of the existing array to the newly allocated one;
Dispose previously aligned chunk with the allocator; the default one uses operator delete().
(Note, that if you're going to write your own vector, your size should increase "M times", not "by fixed amount". This will let you achieve amortized constant time. For example, if, upon each excession of the size limit, your vector grows twice, each element will be copied on average once.)
Same as others are saying, but if you're resizing the array often, one strategy is to resize the array each time by doubling the size. There's an expense to constantly creating new and destroying old, so the doubling theory tries to mitigate this problem by ensuring that there's sufficient room for future elements as well.