Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is accessing data outside an array incorrect if you don't use it?

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?

like image 552
static_rtti Avatar asked Jul 04 '11 14:07

static_rtti


People also ask

Which is correct way of accessing array elements?

Array elements are accessed by using an integer index. Array index starts with 0 and goes till the size of the array minus 1.

Does C++ check array indices within bound?

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].

How do you check if an array is out of bounds Python?

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..

How do you make an array in C++?

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.


5 Answers

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.

like image 79
Armen Tsirunyan Avatar answered Oct 19 '22 04:10

Armen Tsirunyan


Still incorrect, still undefined behaviour. Do the bounds check.

int b = *(a + 3); // dereferencing beyond the array bound.
like image 34
Xeo Avatar answered Oct 19 '22 04:10

Xeo


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.)

like image 30
Alexander Gessler Avatar answered Oct 19 '22 05:10

Alexander Gessler


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.

like image 35
Sander De Dycker Avatar answered Oct 19 '22 03:10

Sander De Dycker


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).

like image 45
Lightness Races in Orbit Avatar answered Oct 19 '22 04:10

Lightness Races in Orbit