My code takes an int input and sets that as the array's size, and I have some test prints that print out the index of the array starting from 0 to 4..
std::cout<<array[0]<<std::endl;
std::cout<<array[1]<<std::endl;
std::cout<<array[2]<<std::endl;
std::cout<<array[3]<<std::endl;
std::cout<<array[4]<<std::endl;
However, I noticed that if the input is smaller than 5, say 2 for instance, then the first two cout print out correctly, but then the rest print out 0 or random numbers like 17 and 135137. Is this an out of bounds thing that happens when you index beyond the array size or is this a problem in my code? (I know I have to change the print statements)
The arrays are dynamically allocated by the way, which I think shouldn't matter.
Is this an out of bounds thing that happens when you index beyond the array size or is this a problem in my code?
Both.
Assuming array itself has a size of at least 5 elements, the initial contents of it before you set the values to anything are undefined; essentially random (they're just whatever happened to be hanging out in that particular block of memory that your array now occupies). If array itself has a size of less than 5, the values are still undefined but accessing them also runs the risk of crashing the program. In either case, the fact that you are printing values beyond the end of the initialized, valid data in your array is a problem with your code.
If you allocate an array of n elements, accessing the (n+1)th element is undefined behaviour (UB). (Note after comments: The (n+1)th element is the element with index n. So if array has only size 3, accessing array[3] already causes UB).
So, yes it is an "out of bounds thing" and it is a problem of your code (because it's you who accesses the array beyond its size.
Why not loop to print out simply the existing element instead of hardcoding the indices?
Related
I just begin learning Fortran, and I come across this issue. Consider the following simple code.
PROGRAM random
INTEGER, DIMENSION(12):: array
PRINT *, array
END PROGRAM random
The array is not assigned value, but can be printed, and it seems to have a few random elements and several zero elements. However, if I consider a shorter array, say I declare
INTEGER, DIMENSION(5):: array
then the printed array has all elements = 0. I wonder what is happening here?
When you define an array and try to look at the values it contains (i.e. by printing) before initialising it, the behaviour is undefined. It depends on compiler to compiler. While one compiler may automatically set all the values to zero (which many of us think that to be the default), another compiler may set it to completely random values. Which is why you are seeing the array values sometimes zero and sometimes not.
However, many of the compilers have options to initialise an unassigned array to zeros at compiler level. It is always advised that one should initialise an array always before using it!
If you do not initialize the variable you are seeing whatever happens to be in the memory that your variable occupies. To initialize your array to 0, use the statement:
integer, dimension(12) :: array
array = 0
If you do not initialize your variable before accessing it, your are using undefined behavior and your program is invalid.
I was trying to define an array in c++
double array[592];
I made a mistake and used "sizeof" command instead of size to limit a loop which printed the elements one by one. Hence, the loop was reading array indices until index 4736. Although these locations do not exist, I was getting garbage instead of segmentation fault for all locations after 592. I'm wondering why I'm not getting segmentation fault.
sizeof gives you the number of bytes the array occupies, not the number of elements it consists of. So as a double requires 8 bytes on your system, the result should become clear.
sizeof(array) // Returns 592 * sizeof(double)
Gives you the total number of bytes occupied by an 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.
Would like to know in C++ what the value of unassigned integer in an int[] usually is.
Example
int arr[5];
arr[1]=2;
arr[3]=4;
for(int i=0;i<5;i++)
{
cout <<arr[i] <<endl;
}
it print
-858993460
2
-858993460
4
-858993460
we know that the array will be {?,2,?,4,?} ,where ? is unknown.
What will the "?" be usually?
When I tested , I always got negative value.
Can I assume in C++ unassigned element in the integer array is always less than or equal to zero?
Correct me if I'm wrong. When I study in Java unassigned element in array will produce null.
Formally, in most cases the very attempt to read an uninitialized value results in undefined behavior. So, formally the question about the actual value is rather moot: you are not allowed to even look at that value directly.
Practically, uninitialized values in C and C++ are unpredictable. On top of that they are not supposed to be stable, meaning that reading the same uninitialized value several times is not guaranteed to read the same value.
If you need a pre-initialized local array, declare it with an explicit initializer
int arr[5] = {};
The above is guaranteed to fill the array with integer zeros.
When I tested , I always got negative value.
The (previously) unused memory space seemed filled with the hex code 0xCC. However, as mentioned above -- several times -- you cannot rely on this.
In one of your comments you clarify your task:
im trying to create an int array let say of the size 100 and randomly insert postive integer into any position in the array. If the array is not full. how could i determine if that position in the array has never been assigned[?]
Fill the array with zeros (manually, or per AndrewT's answer). Since you are inserting positive integers only, all you have to test for is !0.
You can't know what this will produce, since it takes as value the bits that are in memory in that moment. So you can get ANY value, not only negative values.
The values contained in an unitialized area of memory can be anything, it is implementation depending. The most efficient implementation is to leave the memory as it was, so you will find in your array whatever was contained before. An important note: it is not something you can use as a random value. Some implementation (I have seen that, especially in the past, when compiling and running in debug mode) might put zeros in your memory, but it is uncommon. You simply should not rely on the content of uninitialized area of memory.
To understand if something has not been touched in your array, you can initialize it to some value like DEADBEEF:
http://en.wikipedia.org/wiki/Hexspeak
(Unless you are so unlucky that one of the values you have to insert corresponds exactly to DEADBEEF... :) )
These are garbage values, you cannot expect to work with these variables properly and they will not predict what it may result into. Whenever a variable gets allocated some portion of memory gets allocated for that variable and those portion may be used previously for some other unknown calculation which you cannot know, so you have to intialize those variables with some values to avoid usage of garbage values.
You are not assigning any value at these locations. So it will return garbage values from memory. You must put some values at these locations. Unimplemented locations will returned in some unexpected/unpredictable values.
Let's say I have an array like this:
string x[2][55];
If I want to fill it with "-1", is this the correct way:
fill(&x[0][0],&x[2][55],"-1");
That crashed when I tried to run it. If I change x[2][55] to x[1][54] it works but it doesn't init the last element of the array.
Here's an example to prove my point:
string x[2][55];
x[1][54] = "x";
fill(&x[0][0],&x[1][54],"-1");
cout<<x[1][54]<<endl; // this print's "x"
Because when you have a multi-dimensional array, the address beyond the first element is a little confusing to calculate. The simple answer is you do this:
&x[1][55]
Let's consider what a 2d array x[N][M] is laid out in memory
[0][0] [0][1] ... [0][M-1] [1][0] [1][1] ... [1][M-1] [N-1][0] .. [N-1][M-1]
So, the very last element is [N-1][M-1] and the first element beyond is [N-1][M]. If you take the address of [N][M] then you go very far past the end and you overwrite lots of memory.
Another way to calculate the first address beyond the end is to use sizeof.
&x[0][0] + sizeof(x) / sizeof(std::string);
From the formal and pedantic point of view, this is illegal. Reinterpreting a 2D array as a 1D array results in undefined behavior, since you are literally attempting to access 1D x[0] array beyond its boundary.
In practice, this will work (although some code analysis tools might catch an report this as a violation). But in order to specify the pointer to the "element beyond the last" correctly, you have to be careful. It can be specified as &x[1][55] or as &x[2][0] (both are the same address).