1

I have a question regarding the C++ arrays. I am learning C++ and in the "Arrays" section I came across with something that I could not understand.

Suppose we have an integer array with 5 element. The instructor says, in the next line, if we try to get input for the fifth index of the array we cannot know what will happen (e.g. crash or whatnot) because it is operating system and compiler dependent.

int testArray[5] {0};
std::cin >> testArray[5];

Can you enlighten me why this situation is OS/compiler dependent?

test
  • 93
  • 1
  • 11
  • It is true that we cannot know what will happen, but it is not operating system or compiler dependent. It is simply, by definition, not predictable what will happen. – François Andrieux Dec 24 '20 at 18:46
  • Because enforcing some particular behaviour would force compilers to generate code to check for array overflow and that would slow C++ programs down. C++ made the decision a long time ago that's it's your responsibility to check for such things if you wish to. – john Dec 24 '20 at 18:50
  • @FrançoisAndrieux: That is not at all the definition. If X is predictable, that is a property of X. If X is unpredictable, that is a property of X. If we state X must be predictable or X must be unpredictable, we are stating a requirement on X. The definition of *undefined* in the C++ standard is “behavior for which this International Standard imposes no requirements.” The standard does **not** say that undefined behavior is predictable or that undefined behavior is not predictable. It is false to say that the definition means something is unpredictable. – Eric Postpischil Dec 24 '20 at 18:55
  • 1
    FYI, with arrays, the term is *out of bounds*. The term *overflow* usually refers to numbers that are incremented beyond their range. – Thomas Matthews Dec 24 '20 at 19:03

2 Answers2

3

C++ is a systems language. It doesn't mandate any checking on operations: a program which is implemented correctly would be impeded by unnecessary checks, e.g., to verify that an array access is within bounds. The checks would consist of a conditional potentially needed on every access (unless the optimizer can see that some checks can be elided) and potentially also extra memory as the system would need to represent the size of the array for the checks.

As there are no checks, you may end up manipulating bytes outside the memory allocated for the array in question. That may override values used for something else or it may access memory beyond a page boundary. In the latter case the system may be set up to cause segmentation fault. In the former case it may access otherwise unused memory and there may be no ill effect. ... or it may modify the stack in a way preventing the program from correctly returning from a function. However, how the stack is laid out depends on many aspects like the CPU used, the calling conventions on the given system, some compiler preferences. To avoid impeding correct programs there is no mandated behavior when illegal operations are performed. Instead the behavior the program become undefined and anything is OK to happen.

Having behavior undefined is kind of bad if you cause it. The simple solution is not to cause undefined behavior (yes, I know, that is easier said than done). However, leaving behavior undefined is often good performance and it also enables different implementation to actually define the behavior to do something helpful. For example, it makes it legal for implementations to check for undefined behavior and report these cases. Doing something to detect undefined behavior is, e.g., done by -fsanitize=undefined provided by some compilers (I don't think that would cause all kinds of undefined behavior to be detected but it certainly detects some kinds of undefined behavior).

Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380
0

Arrays are not meant to be indexed outside of. C++ made the decision to not actually check these indexes, which means that you can read out of the bounds of an array. It simply tells you that you shouldn't do that, and delegates the out-of-bounds checks to the programmer for added speed.

Since compilers and operating systems and many other factors can determine how memory is laid out, reading out of the bounds of an array can do basically anything, including giving garbage values, segfaulting, or summon nasal demons.

Aplet123
  • 33,825
  • 1
  • 29
  • 55