https://gist.github.com/zedshaw/64b3fb6b7ed653852619
I officially concede that because you can work two pointers on a computer to overwrite another location of memory to alter a for-loop (incidentally, there's not UB listed in ANSI for 'alter the variable of a for-loop') that everyone should go back to writing their C code just as K&R intended.
Please, you all should rely on only the '\0' byte terminator of all strings, don't do any bounds checking, don't check the return code of functions, and you will be totally safe.
Because, UB means "I ain't gotta fix it."
Enjoy, now I'm going painting.
"When an expression that has integer 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 integer 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."
This is a long-winded standards-language way of saying that if you compute x+y, where x is an array and y is not a valid index in the array or one past the end of the array, the behavior is undefined. The moment I computed 'output', I hit UB. Everything that happens after that is up to the whims of the platform.
I guess part of what is scary about C is that it gives you the illusion of a high-level language, but unless you know all UB by heart, you might accidentally start working in assembly.
Isn't there at least a flag that activates warnings for stuff like this? I tried -Wall in both clang and gcc and they didn't say jack shit.
What do modern C developers do these days? Arm themselves with expensive advanced static analysis tools to their teeth?
Static analysis helps a lot, as does being careful about what you write. Most constructs aren't dangerous, so you can mostly avoid the scary ones, and take extra care when you need to use them. Not that this saves you all the time, but it helps.
Compiled with GCC, it doesn't go into an infinite loop. Zed seems to think this makes your example a "fail". This is curious since the whole quibble is about functions that work in some context but fail when brought into a different context.
Edit: FWIW, safercopy also has undefined behavior when from_length and to_length are larger than MAX_INT.
https://gist.github.com/zedshaw/81edf35857e137ccd7d3 is the results.
There's no need to run it for 24 hours. Just run it, then pause in the debugger and step through a few loops. It'll be evident that nothing changes.
If you need help getting it to work properly on your own setup, let me know.