C++ Calculating the number of bytes in an array of integers - c++

This may or may not be a very simple question, but I would like to know what function to call in order to figure out how many bytes are in an array at any given time. For example, how would I know what to put as the third argument in the send command in the code below?
int *array= new int[500];
memset(array, 0, sizeof(array));
//newsockfd is declared elsewhere in the code
send(newsockfd, array, _______, 0);

The size of an array is constant (it's just a hunk of memory).
You'll need to keep track of how many elements of the array are valid yourself, in a separate variable.
As others have noted, the last argument to memset should be the number of bytes you want set to 0 -- but array is just a pointer, so sizeof(array) will yield only 4 (or 8 on a 64-bit platform). Again, you'll need to manually pass in sizeof(int) * 500 (or use a constant for the 500 so you don't have to update the number in multiple places if it changes).

There is no way that you can get count of items that dynamically allocated for an array, so the line memset(array, 0, sizeof(array)) do not fill 500 items in array with 0, and sizeof(array) is always equal to sizeof(int*), so if you want to have access to count of items that allocated for an array, you should either use a separate value that contain the size or use C++ storages like std::vector

Your memset() doesn't clear the dynamicly allocated memory new int[500], but just the first sizeof(int*) bytes.
If you want to clear the heap memory, do it this way:
memset(array, 0, 500 * sizeof(int));
or at initialization time:
int *array= new int[500]();

Also look at www.cplusplus.com/faq/sequences/arrays/sizeof-array/ is a good reading about the subject (not directly about the sizeof() operator but handling arrays in C++ in general, in a proper "C++ way").

Related

C++ memcpy to end of an array

I'm trying to translate C++ into C# and I'm trying to understand, conceptually what the following piece of code does:
memcpy( pQuotes + iStart, pCurQuotes + iSrc, iNumQuotes * sizeof( Quotation ) );
pQuotes is declared: struct Quotation *pQuotes.
pCurQuotes is a CArray of struct Quoataion, iSrc being it's first index. iNumQuotes is the number of elements in pCurQuotes.
What I would like to know is, if iStart is to pQuotes' last index, would the size of pQuotes be increased to accommodate the number of elements in pCurQuotes? In other words, is this function resizing the array then appending to it?
Thanks.
SethMo
If iStart is to pQuotes' last index, would the size of pQuotes be
increased to accommodate the number of elements in pCurQuotes? In
other words, is this function resizing the array then appending to it?
No.
This is a fundamental limitation of these low-level memory functions. It is your responsibility as the developer to ensure that all buffers are big enough so that you never read or write outside the buffer.
Conceptually, what happens here is that the program will just copy the raw bytes from the source buffer into the destination buffer. It does not perform any bounds- or type-checking. For your problem of converting this to C# the second point is of particular importance, as there are no type conversions invoked during the copying.
would the size of pQuotes be increased to accommodate the number of elements in pCurQuotes?
No. The caller is expected to make sure before making a call to memcpy that pQuotes points to a block of memory sufficient to accommodate iStart+iNumQuotes elements of size sizeof(Quotation).
If you model this behavior with an array Quotation[] in C#, you need to extend the array to size at or above iStart+iNumQuotes elements.
If you are modeling it with List<Quotation>, you could call Add(...) in a loop, and let List<T> handle re-allocations for you.
No, memcpy does not do any resizing. pQuotes is merely a pointer to a space in memory, and the type of pointer determines its size for pointer arithmetic.
All that memcpy does is copy n bytes from a source to a destination. You need to apply some defensive programming techniques to ensure that you do not write beyond the size of your destination, because memcpy won't prevent it!

How can I find the memory used by my array

I have seen this asked in different forms, and I have been reading up on it, but I am still confused on how to find the memory used. I have an array it is being pointed to by a pointer the value *ptr = the number of elements in the array. I need the total size of the array and its elements (it is an array of short int and it has 14 elements total). I am confused on how to get this value of memory used by the array + memory used by the elements, would I just use size of and then add the two. This is where I keep running into issues. Can someone point me in the right direction?
To get the size in bytes of the array, you would have to calculate it using sizeof(short int) * number_of_elements, where number_of_elements is 14.
Instead of raw arrays, e.g., int ar[4], use std::array from <array>. Such array provides bounds checking for debug mode and, unlike raw arrays, can easily be copied and used as a function's argument. It also provides a size() method.

Dynamic and static array

I am studying C++ reading Stroustrup's book that in my opinion is not very clear in this topic (arrays). From what I have understood C++ has (like Delphi) two kind of arrays:
Static arrays that are declared like
int test[3] = {10,487,-22};
Dynamic arrays that are called vectors
std::vector<int> a;
a.push_back(10);
a.push_back(487);
a.push_back(-22);
I have already seen answers about this (and there were tons of lines and concepts inside) but they didn't clarify me the concept.
From what I have understood vectors consume more memory but they can change their size (dynamically, in fact). Arrays instead have a fixed size that is given at compile time.
In the chapter Stroustrup said that vectors are safe while arrays aren't, whithout explaining the reason. I trust him indeed, but why? Is the reason safety related to the location of the memory? (heap/stack)
I would like to know why I am using vectors if they are safe.
The reason arrays are unsafe is because of memory leaks.
If you declare a dynamic array
int * arr = new int[size]
and you don't do delete [] arr, then the memory remains uncleared and this is known as a memory leak. It should be noted, ANY time you use the word new in C++, there must be a delete somewhere in there to free that memory. If you use malloc(), then free() should be used.
http://ptolemy.eecs.berkeley.edu/ptolemyclassic/almagest/docs/prog/html/ptlang.doc7.html
It is also very easy to go out of bounds in an array, for example inserting a value in an index larger than its size -1. With a vector, you can push_back() as many elements as you want and the vector will resize automatically. If you have an array of size 15 and you try to say arr[18] = x,
Then you will get a segmentation fault. The program will compile, but will crash when it reaches a statement that puts it out of the array bounds.
In general when you have large code, arrays are used infrequently. Vectors are objectively superior in almost every way, and so using arrays becomes sort of pointless.
EDIT: As Paul McKenzie pointed out in the comments, going out of array bounds does not guarantee a segmentation fault, but rather is undefined behavior and is up to the compiler to determine what happens
Let us take the case of reading numbers from a file.
We don't know how many numbers are in the file.
To declare an array to hold the numbers, we need to know the capacity or quantity, which is unknown. We could pick a number like 64. If the file has more than 64 numbers, we start overwriting the array. If the file has fewer than 64 (like 16), we are wasting memory (by not using 48 slots). What we need is to dynamically adjust the size of the container (array).
To dynamically adjust the capacity of an array, a new larger array must be created, then elements copied and the old array deleted.
The std::vector will adjust its capacity as necessary. It handles the dynamic allocation of memory for you.
Another aspect is the passing of the container to a function. With an array, you need to pass the array and the capacity. With std::vector, you only need to pass the vector. The vector object can be queried about its capacity.
One Security I can see is that you can't access something in vector which is not there.
What I meant by that is , if you push_back only 4 elements and you try to access index 7 , then it will throw back an error. But in array that doesn't happen.
In short, it stops you from accessing corrupt data.
edit :
programmer has to compare the index with vector.size() to throw an error. and it doesn't happne automatically. One has to do it by himself/herself.

C++ doesn't tell you the size of a dynamic array. But why?

I know that there is no way in C++ to obtain the size of a dynamically created array, such as:
int* a;
a = new int[n];
What I would like to know is: Why? Did people just forget this in the specification of C++, or is there a technical reason for this?
Isn't the information stored somewhere? After all, the command
delete[] a;
seems to know how much memory it has to release, so it seems to me that delete[] has some way of knowing the size of a.
It's a follow on from the fundamental rule of "don't pay for what you don't need". In your example delete[] a; doesn't need to know the size of the array, because int doesn't have a destructor. If you had written:
std::string* a;
a = new std::string[n];
...
delete [] a;
Then the delete has to call destructors (and needs to know how many to call) - in which case the new has to save that count. However, given it doesn't need to be saved on all occasions, Bjarne decided not to give access to it.
(In hindsight, I think this was a mistake ...)
Even with int of course, something has to know about the size of the allocated memory, but:
Many allocators round up the size to some convenient multiple (say 64 bytes) for alignment and convenience reasons. The allocator knows that a block is 64 bytes long - but it doesn't know whether that is because n was 1 ... or 16.
The C++ run-time library may not have access to the size of the allocated block. If for example, new and delete are using malloc and free under the hood, then the C++ library has no way to know the size of a block returned by malloc. (Usually of course, new and malloc are both part of the same library - but not always.)
One fundamental reason is that there is no difference between a pointer to the first element of a dynamically allocated array of T and a pointer to any other T.
Consider a fictitious function that returns the number of elements a pointer points to.
Let's call it "size".
Sounds really nice, right?
If it weren't for the fact that all pointers are created equal:
char* p = new char[10];
size_t ps = size(p+1); // What?
char a[10] = {0};
size_t as = size(a); // Hmm...
size_t bs = size(a + 1); // Wut?
char i = 0;
size_t is = size(&i); // OK?
You could argue that the first should be 9, the second 10, the third 9, and the last 1, but to accomplish this you need to add a "size tag" on every single object.
A char will require 128 bits of storage (because of alignment) on a 64-bit machine. This is sixteen times more than what is necessary.
(Above, the ten-character array a would require at least 168 bytes.)
This may be convenient, but it's also unacceptably expensive.
You could of course envision a version that is only well-defined if the argument really is a pointer to the first element of a dynamic allocation by the default operator new, but this isn't nearly as useful as one might think.
You are right that some part of the system will have to know something about the size. But getting that information is probably not covered by the API of memory management system (think malloc/free), and the exact size that you requested may not be known, because it may have been rounded up.
You will often find that memory managers will only allocate space in a certain multiple, 64 bytes for example.
So, you may ask for new int[4], i.e. 16 bytes, but the memory manager will allocate 64 bytes for your request. To free this memory it doesn't need to know how much memory you asked for, only that it has allocated you one block of 64 bytes.
The next question may be, can it not store the requested size? This is an added overhead which not everybody is prepared to pay for. An Arduino Uno for example only has 2k of RAM, and in that context 4 bytes for each allocation suddenly becomes significant.
If you need that functionality then you have std::vector (or equivalent), or you have higher-level languages. C/C++ was designed to enable you to work with as little overhead as you choose to make use of, this being one example.
There is a curious case of overloading the operator delete that I found in the form of:
void operator delete[](void *p, size_t size);
The parameter size seems to default to the size (in bytes) of the block of memory to which void *p points. If this is true, it is reasonable to at least hope that it has a value passed by the invocation of operator new and, therefore, would merely need to be divided by sizeof(type) to deliver the number of elements stored in the array.
As for the "why" part of your question, Martin's rule of "don't pay for what you don't need" seems the most logical.
There's no way to know how you are going to use that array.
The allocation size does not necessarily match the element number so you cannot just use the allocation size (even if it was available).
This is a deep flaw in other languages not in C++.
You achieve the functionality you desire with std::vector yet still retain raw access to arrays. Retaining that raw access is critical for any code that actually has to do some work.
Many times you will perform operations on subsets of the array and when you have extra book-keeping built into the language you have to reallocate the sub-arrays and copy the data out to manipulate them with an API that expects a managed array.
Just consider the trite case of sorting the data elements.
If you have managed arrays then you can't use recursion without copying data to create new sub-arrays to pass recursively.
Another example is an FFT which recursively manipulates the data starting with 2x2 "butterflies" and works its way back to the whole array.
To fix the managed array you now need "something else" to patch over this defect and that "something else" is called 'iterators'. (You now have managed arrays but almost never pass them to any functions because you need iterators +90% of the time.)
The size of an array allocated with new[] is not visibly stored anywhere, so you can't access it. And new[] operator doesn't return an array, just a pointer to the array's first element. If you want to know the size of a dynamic array, you must store it manually or use classes from libraries such as std::vector

Is dynamic memory deletion also possible in arrays?

Supposingly I've declared a character array and take a string from the user as follows:
char s[100000];
std::cin>>s;
Now say the user has entered the string "Program". My character array will be as as follows:
'P''r''o''g''r''a''m''\0'......(99992 remaining indices with no/junk values)
Is there a way to free the space occupied those 99992 indices? Similarly if I've an integer array of size say 100000 and I'm using only first 10 indices during run time, is there a way to resize my array during the run time of my program. I know we can use vectors for this purpose but is the thing possible somehow using arrays? For integer arrays, I know we may declare arrays dynamically and then declare size as per our requirement but say I have array of 10 integers as follows:
1 2 3 4 5 6 7 8 9 10
Now, I want to use only first 9 indices and wnat to kind of delete the 10th index. In other words, along with dynamic allocation, is dynamic deletion also possible with arrays?
EDIT:
I know the thing is possible using STLs but I want to know if we can do the same thing in arrays?
No.
If you have arrays defined with a fixed size, you cannot release part of those arrays at run-time. Use a dynamically allocated array of some sort — probably a string or vector<int> for your two example arrays respectively, though a vector<char> might also work sufficiently well for you.
When you write:
char s[100000];
You are telling the compiler to stack 100000 bytes in the program stack.
However when you reserve memory dynamically:
char * = new char[100000];
You are asking the system to reserve 100000 bytes in the heap so you can handle that asked memory as you want, even tell the system to free it as a resource.
You can't free memory at the stack until your local context is finished. For example, exiting the function you where you declared char s[100000].
Check this question:
What and where are the stack and heap?
std::string is implemented using dynamic memory allocation at the heap and that is why it allows you to reduce its size.
that is not possible.
you may wrap your user input capturing in a subroutine that allocates stack space and allocates heap memory at the actual required length.
You are confused over when to use static allocation and when to use dynamic allocation.
Static allocation is used when the maximum number of items is known in advance, at compile-time.
Dynamic allocation is used when the number of items is unknown until run-time.
There exists no other case than the two above. You cannot mix them and it wouldn't make sense to do so.
The only case where you should allocate a static array char s[100000]; is the case where you know, at some point, that there will be 100000 items that the program needs to handle.
You designed your program to handle the worst case of 100000 items. It must still be able to handle that many. If the program needs to have an array of variable, unknown size, you should have used dynamic allocation.
If we ignore that C++ exists, then what you would have done in C is this:
char* s = malloc(sizeof(*s) * 100000);
...
s = realloc(s, some_strlenght);
Please note that huge static arrays allocated on the stack is bad practice in many operative systems. So you might have to declare the 100000 array on the heap anyway, even though you won't resize it. Simply because there is likely not enough stack space in your process to declare large, bulky variables like that.
(Also, because of the way C++ is designed, std::string and std::vector etc are always implemented with dynamic memory internally, even if you only use them with one fixed size.)