In an algorithm I'm writing, I can have the following (simplified of course)
int a[3] = {1,2,3};
int b = a[3];
when the index used to fill b
overflows, I never use the value of b. Is the code still incorrect? Do I have to make an explicit boundary check?
Array elements are accessed by using an integer index. Array index starts with 0 and goes till the size of the array minus 1.
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].
Another way of checking if an array is out of bounds is to make a function. This will check if the index is "in bounds". If the index is below zero or over the array length you will get the result false. This should be built in as a member function of the array class..
A typical declaration for an array in C++ is: type name [elements]; where type is a valid type (such as int, float ...), name is a valid identifier and the elements field (which is always enclosed in square brackets [] ), specifies the size of the array.
This code has Undefined Behavior whether or not you use b
. Why? Because a[3]
is equivalent to *(a+3)
by definition. And here's a quote from the standard that proved that *(a+3)
is in itself undefined, regardless of whether the value is stored, used, or left alone.
When an expression that has integral type is added to or subtracted from a pointer, the result has the type of the pointer operand. If the pointer operand points to an element of an array object, and the array is large enough, the result points to an element offset from the original element such that the difference of the subscripts of the resulting and original array elements equals the integral expression. In other words, if the expression P points to the i-th element of an array object, the expressions (P)+N (equivalently, N+(P)) and (P)-N (where N has the value n) point to, respectively, the i+n-th and i−n-th elements of the array object, provided they exist. Moreover, if the expression P points to the last element of an array object, the expression (P)+1 points one past the last element of the array object, and if the expression Q points one past the last element of an array object, the expression (Q)-1 points to the last element of the array object. If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined.
Still incorrect, still undefined behaviour. Do the bounds check.
int b = *(a + 3); // dereferencing beyond the array bound.
Reading a[3]
already causes undefined behaviour. As undefined behaviour is never locally limited, this can already lead to your harddisk drive being formatted or your computer emerging to a giant, flesh-eating zombie.
In reality, it will usually just work. But it's easy to make up a case where the end of the array marks the end of a mapped memory region, so accessing one element beyond would cause a segmentation fault. This is certainly not the case for an array of int
on the stack and neither with most heap implementations, but you shouldn't rely on it.
(Whether taking the address of &a[3]
is undefined behaviour as well is heavily disputed.)
It's still incorrect yes, because you access the out-of-bounds memory location to get the value a[3]
and store it in the variable b
.
The fact that you never use b
could mean that the compiler optimizes out that line of code, so you might not ever see any adverse effects from that line being there.
However, the compiler is not required to do so, and the code itself still has undefined behavior.
Yes.
You are using the value, by copying it into b
.
More specifically, dereferencing (a+3)
is not allowed since the expression (a+3)
is not a valid pointer... and the expression a[3]
is equivalent to *(a+3)
(where a
has decayed to a pointer-expression).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With