I am assigning values in a C++ program out of the bounds like this:
#include <iostream>
using namespace std;
int main()
{
int array[2];
array[0] = 1;
array[1] = 2;
array[3] = 3;
array[4] = 4;
cout << array[3] << endl;
cout << array[4] << endl;
return 0;
}
The program prints 3
and 4
. It should be not be possible. I am using g++ 4.3.3
Here is compile and run command
$ g++ -W -Wall errorRange.cpp -o errorRange
$ ./errorRange
3
4
Only when assigning array[3000]=3000
does it give me a segmentation fault.
If gcc doesnt check for array bounds, how can I be sure if my program is correct, as it can lead to some serious issues later?
I replaced above code with
vector<int> vint(2);
vint[0] = 0;
vint[1] = 1;
vint[2] = 2;
vint[5] = 5;
cout << vint[2] << endl;
cout << vint[5] << endl;
and this one is also produces no error.
As mentioned now in the question using std::vector::at will solve the problem and make a bound check before accessing.
If you need a constant size array that is located on the stack as your first code use the C++11 new container std::array; as vector there is std::array::at function. In fact the function exists in all standard containers in which it have a meaning,i.e, where operator[] is defined :( deque, map, unordered_map) with the exception of std::bitset in which it is called std::bitset::test.
If you change your program slightly:
(Changes in capitals -- put those in lower case if you're going to try this.)
You will see that the variable foo has been trashed. Your code will store values into the nonexistent array[3] and array[4], and be able to properly retrieve them, but the actual storage used will be from foo.
So you can "get away" with exceeding the bounds of the array in your original example, but at the cost of causing damage elsewhere -- damage which may prove to be very hard to diagnose.
As to why there is no automatic bounds checking -- a correctly written program does not need it. Once that has been done, there is no reason to do run-time bounds checking and doing so would just slow down the program. Best to get that all figured out during design and coding.
C++ is based on C, which was designed to be as close to assembly language as possible.
You are certainly overwriting your stack, but the program is simple enough that effects of this go unnoticed.
It's undefined behavior as far as I know. Run a larger program with that and it will crash somewhere along the way. Bounds checking is not a part of raw arrays (or even std::vector).
Use std::vector with
std::vector::iterator
's instead so you don't have to worry about it.Edit:
Just for fun, run this and see how long until you crash:
Edit2:
Don't run that.
Edit3:
OK, here is a quick lesson on arrays and their relationships with pointers:
When you use array indexing, you are really using a pointer in disguise (called a "reference"), that is automatically dereferenced. This is why instead of *(array[1]), array[1] automatically returns the value at that value.
When you have a pointer to an array, like this:
Then the "array" in the second declaration is really decaying to a pointer to the first array. This is equivalent behavior to this:
When you try to access beyond what you allocated, you are really just using a pointer to other memory (which C++ won't complain about). Taking my example program above, that is equivalent to this:
The compiler won't complain because in programming, you often have to communicate with other programs, especially the operating system. This is done with pointers quite a bit.
C or C++ will not check the bounds of an array access.
You are allocating the array on the stack. Indexing the array via
array[3]
is equivalent to *(array + 3)
, where array is a pointer to &array[0]. This will result in undefined behavior.One way to catch this sometimes in C is to use a static checker, such as splint. If you run:
on,
then you will get the warning: