Reputation: 8268
The detailed explanation for the undefined-behavior tag starts very reasonably:
In computer programming, undefined behavior (informally "UB") refers to computer code whose behavior is not specified by the programming language standard under certain conditions.
but then says (emphasis mine):
Questions regarding the various forms of documented undefined behavior in the given programming language.
How can "behavior" that is "not specified" be "documented"?
What is "documented undefined behavior" and which languages have that beast?
[Additional comment:
Different people have interpreted the previous quoted text in widely different ways, even with opposite meanings, so this question became essentially a request for clarification and rewrite of the text, something which would naturally fit on meta. But the question was not primarily a request of a change of a tag explanation, but a programming language questions, hence it was intentionally not posted on meta.
(Note: I already brought up on meta the issue of that text multiple times, both in a question and an answer, but each time my comments were deleted, in a very harsh way.)]
EDIT
please edit to explain in detail the parts of your question that are unique
The unique parts are, again:
None of linked question answers these; the words documented undefined behavior don't even appear together.
If I missed something, it would be helpful to point specifically to the answers that explain those.
I would be sad that yet another question, answer, or discussion about UB would be deleted, because it points to inconsistencies in the tag description.
Upvotes: 1
Views: 487
Reputation: 81189
C and C++ are rather unique, in that the "official" C standards was written long after the language was already in use, and had even been described in published books. There were many situations such as integer overflow which some implementations would process in documented predictable fashion but others could not do so cheaply. The Standard treats such things as "Undefined Behavior", expressly noting that implementation may (but are not required) to process them in a documented fashion characteristic of the environment. Note that this allows for the possibility that in some environments it might be expensive to guarantee any kind of consistent behavior, and that many programs might not offer from such guarantees despite the cost.
Consider, for example, something like:
extern volatile int someFlag;
void test(int x, int y)
{
int z;
someFlag = 1;
z=x+y;
someFlag = 0;
if (f2())
f3(x,y,z);
}
Should an implementation where overflow raises a signal be allowed to change the code to:
extern volatile sig_atomic_t someFlag;
void test(int x, int y)
{
someFlag = 1;
someFlag = 0;
if (f2())
f3(x,y,x+y);
}
Doing so would avoid the need to save the value of x+y
in memory across the call to f2()
, and might avoid the need to compute it altogether. A net win unless someFlag
would affect the behavior of the integer-overflow signal in a fashion that code was relying upon. If the Standard had characterized integer overflow as "Implementation Defined", it would have been awkward for implementations to document overflow behavior as required by the Standard without foregoing optimizations like the above, even though for many purposes a guarantee that the addition would be performed before the call to f2
would add cost but not any value.
Rather than try to worry about whether such optimizations should be allowed or prohibited, the authors of the Standard opted to characterize integer overflow as Undefined Behavior, allowing implementations that documented its behavior to continue doing so, but not requiring that implementations pessimistically assume that any possible side-effects might be observable in ways they don't know about. Before the Standard was written, any behaviors that an implementation documented would be documented behaviors, and the fact that the Standard characterized behaviors as Undefined was not intended to change that.
Since then, there have been a number of defect reports which incorrectly describe as "non-conforming" various constructs which are conforming but not strictly conforming, and this has contributed to a mistaken belief that the term "X is undefined" in the Standard is equivalent to "X is forbidden". Other language specifications are far more explicit in distinguishing between constructs which are forbidden and must be diagnosed, those which are forbidden but may not always be diagnosed, those whose behavior is expected to be partially but not fully consistent, and those whose behavior will behave in different consistent fashions on different implementations, but the authors of the original C and C++ Standards left such things to implementers' judgment.
Upvotes: 1
Reputation: 214080
I was the one who wrote that text in the wiki. What I meant with "documented undefined behavior" is something which is formally undefined behavior in the language standard, but perfectly well-defined in the real world. No language has "documented undefined behavior", but the real world doesn't always care about what the language standard says.
A better term would perhaps be non-standard language extensions, or if you will "undefined as far as the programming language standard is concerned".
There are several reasons why something could be regarded as undefined behavior in the language standard:
Example of 1)
Where are variables stored in memory? This is outside the scope of the standard yet perfectly well-defined on any computer where programs are executed.
Similarly, if I say "my cat is black", it is undefined behavior, because the color of cats isn't covered by the programming language. This doesn't mean that my cat will suddenly start to shimmer in a caleidoscope of mysterious colors, but rather that reality takes precedence over theoretical programming standards. We can be perfectly certain that the specific cat will always be a black cat, even though it is undefined behavior.
Example of 2)
Signed integer overflow. What happens in case of integer overflow is perfectly well-defined on the CPU level. In most cases the value itself will get treated as simple unsigned addition/subtraction, but an overflow flag will be set in a status register. As far as the C or C++ language is concerned, such overflows might in theory cause dreadful, unexplained events to happen. But in reality, the underlying hardware will produce perfectly well-defined results.
Example of 3)
Division by zero. Accessing invalid addresses. The behavior upon stack overflow. Etc.
Upvotes: 2
Reputation: 51
As I read it, "documented undefined behavior" doesn't mean "behavior that is both (undefined AND documented)". It means "(undefined behavior) which is documented". He even gives an example:
For example, accessing beyond the last element of an array in C might be diagnosed by the compiler if the array index is known during compilation, or might return a garbage value from uninitialized memory, or return an apparently sensible value, or cause the program to crash by accessing memory outside the process' data address space.
The undefined behavior is "accessing beyond the last element of an array in C". The C language says, THIS IS UNDEFINED. And yet, he and others have documented what things actually DO happen in the real word when you enter this "undefined" area of the language.
So there's two levels at which this undefined behavior is documented.
1) It is identified. "C doesn't define what happens when you go past the end of the array". Now you know it's undefined behavior.
2) It is explored. "Here are some things that can happen when you do it."
Maybe the author intended meaning 1 or meaning 2. Or some other meaning. But I think the meaning you're chasing may be an artifact of reading the phrase differently than I did.
Upvotes: 0