1

It just happened to me. A bug. I set a 5 element array and a position variable to scroll through all its index:

int matematica[5];
int pos = 0;

and then I had my loop working just ok. Like this:

while (pos < 5) {
    printf("Entre com o número da matrícula do %dº aluno: \n", pos+1);
    scanf("%d", &num);
    if (num != 35)
        matematica[pos] = num;
    pos++;
}

Everything working like a charm. After that, I had do the same to 150 positions, so I changed the while loop from while (pos < 5) to while (pos < 150) but forgot to do the same with the array. What happened then is the object of my question itself. The program didn't crash or something, it just happened that the printf and scanf statements run a bit more than 5 times then stops (sometimes 8 times, sometimes 7...)

Why does that happens. I of course fixed it later, but I still can't grasp the logic behind that bug.

Ezequiel Barbosa
  • 211
  • 1
  • 15
  • 5
    Pretty much anything at all can happen. The [standard hyperbole](http://www.catb.org/jargon/html/N/nasal-demons.html) is that the compiler is allowed to make demons fly out your nose. – user2357112 May 31 '15 at 01:38
  • 1
    You invoked undefined behavior, which by its very definition cannot be definitively explained. – DavidO May 31 '15 at 01:40
  • "Why does that happens " - It happens for no definitive reason whatsoever. Thus the nature of *undefined behavior*, which is precisely what you told your program to invoke: nonsense. – WhozCraig May 31 '15 at 01:42
  • Related to [Is accessing a global array outside its bound undefined behavior?](http://stackoverflow.com/q/26426910/1708801) maybe a duplicate – Shafik Yaghmour May 31 '15 at 02:13
  • Is this array global or local to a function? – M.M May 31 '15 at 02:24
  • Learn about `virtual memory layout` on linux will help you understand what might happan? – Eric May 31 '15 at 02:45

2 Answers2

5

The C standard says this triggers Undefined behavior,

anything could happen.

  • It could appear to work "correctly"
  • it could terminate with an error code.
  • it could do something unexpected.

This type of bug is called a buffer overrun, and these can often lead to arbitrary code execution (which is a special subclass of "something unexpected")

In your example pos probably occupies the same memory as matematica[5], (because most (all?) compilers pack global variables together much like fields in a struct) so depending on what number you enter in the sixth place the loop may stop or continue, negative numbers could cause interesting results.

Jasen
  • 11,837
  • 2
  • 30
  • 48
  • 1
    `pos` is not necessarily after (i.e. a larger address) than `matematica`. It depends on which way the stack (I'm assuming this is a local variable) grows and probably other factors (i.e. it's compiler dependent). – Fiddling Bits May 31 '15 at 02:06
  • I've not encounterd a compiler that arranged globals differently when they are of the same base type, but there is no guarantee.but yeah, in in a auto (=local) variable addressing is even less predictable. – Jasen May 31 '15 at 02:13
-3

When you declare your array to be the array of 5 integers, you reserve a chunk of memory which holds it and then, you receive a pointer to it (which you can use however you want). When you call for an array like matematica[0], then you point to the beginning of an array and use value, which is out there. Then, when you call matematica[6] (which is outside the boundaries), you still reach the very same memory, but outside your array. It is totally legal, but it is unknown what is stored there. When you upload any other value there, you might overwrite your own data and cause weird bugs, and when you try to read it, it will be probably a random number. It will not crash, but you are warned :)

irchris102
  • 108
  • 10
  • `matematica[5]` is also outside the boundaries – M.M May 31 '15 at 02:14
  • @FiddlingBits in the C standard, *allocate* only refers to space allocated by `malloc` and friends; although it's common usage to say things like "stack allocation" or "automatic allocation" or "static allocation" – M.M May 31 '15 at 02:16
  • 2
    "It is totally legal" - no, it's not. Accessing memory outside the array is only one possible result; it is not at all guaranteed behavior. – user2357112 May 31 '15 at 02:18
  • Well, right.. Changed it to not make any unspoken, misleading suggestions. By 'totally legal' i meant that if we don't fall outside memory, we can call it and it probably won't crash. – irchris102 May 31 '15 at 02:19
  • "you still reach the very same memory" may be a common experience, but is not specified behavior of C. "It is totally legal" is outright wrong. "It will not crash" may/may not happen . – chux - Reinstate Monica May 31 '15 at 02:21
  • There might not be any memory outside the array. For example, if the array is at the end of the address space; or if the OS gives processes a virtual address space (modern OSs do that) and the addresses after the array are not mapped to any physical memory. – M.M May 31 '15 at 02:22
  • Why did they downvote @irchris102 . Though "totally legal" may not be the most appropriate wording, his answer is just right -by the way the only one that gave me a real insight of what happened - the concept behind is just right. That's precisely the object of my question. I think Stack Overflow should prevent people from downvoting without having answered the question, seems like people just read in a hurry and just straight clik "Downvote". – Ezequiel Barbosa May 31 '15 at 13:24
  • 1
    @irchris102, accessing memory outside the bounds of an array that is on the stack is accessing the memory of the other variables on the stack, the function return address, the variables passed from the calling function, the variables and return address of any called functions, the stack frame pointers, etc etc etc. What the specific result will be could be most anything. That is why it is called 'undefined behavior'. – user3629249 Jun 01 '15 at 05:52
  • 1
    @Ezequiel Barbosa this answer is not just right as it asserts functionality that is not defined. Even it this answer matches your experience, to ascribe behavior based upon experience and contradicted by specification leads to future coding pitfalls in assuming "you still reach the very same memory" and "It will not crash". Many a _good_ answer about Undefined Behavior (UB) describes what likely happened in OP's case, but does not contend that is proscribed behavior like this one does. – chux - Reinstate Monica Jun 01 '15 at 18:33
  • Ok, just to finish this case once and for all... Sometimes I believe that simplified answer is more educational for a person than specifying dozens of different behaviours which might happen. I strongly believe that my example is much simplier to imagine and memorize than just saying it is undefined and trying to point out every possibility and, in fact, has the very same outcome - person who imagine that is not likely to mess with other variables' (pointers' etc.) or reach boundaries of memory. If question was REALLY about all possibilities, one would just look at docs without asking here... – irchris102 Jun 01 '15 at 23:03