0

Possible Duplicate:
Undefined, unspecified and implementation-defined behavior

I'm trying to deepen my understanding of undefined behavior in C++. Suppose a C++ compiler will intentionally detect some cases of undefined behavior - for example, modifying the variable twice between two sequence points:

x++ = 2;

Once that imaginary compiler reliably detects such a situation it will say emit ten totally random machine instructions into the produced machine code.

According to C++ standard, wherever something is classified as UB there're no requirements on what happens. Will the described imaginary compiler be conformant to the C++ standard?

Community
  • 1
  • 1
sharptooth
  • 167,383
  • 100
  • 513
  • 979
  • 6
    It wouldn't be a very popular compiler. – Alex Brown Nov 24 '10 at 09:25
  • The accepted answer to [the very question you link to](http://stackoverflow.com/questions/2397984/undefined-unspecified-and-implementation-defined-behavior) says "Basically, the standard allows anything to happen once you invoke undefined behavior (even nasal demons)." Now tell me why we should __not__ close yours as a dupe? – sbi Nov 24 '10 at 09:29
  • @sbi: Maybe you're right, yet nasal demons are not that easy to implement in the compiler and I prefer to focus on real (even if they are unlikely) things. – sharptooth Nov 24 '10 at 09:39
  • 1
    @sharptooth: Your question reads: "Is the compiler allowed to...", the answer reads "Basically, the standard allows anything to happen". That's a clear dupe to me. I now see that there's something else asked, too, at the end of the question's fine print. If that's what you actually meant to ask, you might want to change your question's title, before this gets closed. – sbi Nov 24 '10 at 09:57
  • @sbi: What exactly do you attribute as fine print in this question? I tried to make it as clear as possible. If there's a way to improve it I'd like to know. – sharptooth Nov 24 '10 at 10:02
  • @sbi, I'm sorry. I did mean sharptooth. – Matthew Flaschen Nov 24 '10 at 10:25
  • @sharptooth: Frankly, I'm at a loss as to what to say without repeating myself. Your question is "Is the compiler allowed to...", which is covered by the question you linked to ("anything is allowed"), which makes this a dupe, which made me vote to close it. If there's anything unclear in this logic, I honestly don't know how to explain it. Is it me or you? – sbi Nov 24 '10 at 10:56
  • @sbi: Okay, I see your point now. Maybe you're right, but I've read that question and a lot of others and my goal is to focus on extreme yet specific examples - because while you know that it's more probable to die for *any reason* people in general are more willing to pay for insurance against dying of something specific - the same way as with floods and earthquakes - http://www.google.com/search?tbs=bks%3A1&tbo=1&hl=en&q=Amos+Tversky+earthquake+in+california+causing+a+flood&btnG=Search+Books – sharptooth Nov 24 '10 at 11:23
  • In your title you speak of "encountering a construct" while in the text you say "intentionally detect", which is much more limited, and suggests you're asking if the compiler has the right to be deliberately malicious if it should so choose? Is that really your concern? If it is, I don't think you'd need to prove that the Standard forbids it before prosecuting them for malicious abuse of your IT system. – Tony Delroy Nov 24 '10 at 11:39
  • @Tony: No, that's not my concern. I just tried to find an extreme example - deliberately emitting random code. – sharptooth Nov 24 '10 at 11:39
  • @sharptooth: deliberately emitting random code but not being deliberately malicious... no... I can promise you that is IMPOSSIBLE (because random code has a non-0 probability - however slight - of doing something malicious, and every compiler writer knows it). – Tony Delroy Nov 24 '10 at 11:43
  • Undefined behavior gives compiler writers even more freedom than that, a fact modern compilers love to exploit. A method like `uint32_t counts[64]; uint32_t shift(uint32_t *arr, uint32_t v, uint8_t s) { if (s < 64) arr[s]++; if (s >= 32) v=0; return v << s;}` would probably work as expected in just about every compiler made before 2010 or so, even when invoked as `shift(counts, 1, 64);`. A new compiler, however, may very well clobber the word past the end of the array. – supercat Apr 16 '15 at 18:38

4 Answers4

9

Yes. The standard imposes no requirements, so it can do whatever it wants:

undefined behavior

behavior, such as might arise upon use of an erroneous program construct or erroneous data, for which this International Standard imposes no requirements.

Just as a note, that is undefined behavior, but it's not necessarily a good example. On g++ 4.4.1, it will refuse to compile with:

error: lvalue required as left operand of assignment

because the result of a post-increment is not an lvalue.

Matthew Flaschen
  • 278,309
  • 50
  • 514
  • 539
3

Essentially, yes, if and only if those 10 instructions are equally reachable. Consider the following code:

int main () {
  if (false) {
    int x = 0; x++ = 2;
  }
  std::cout << "Hello, world" << std::endl;
}

The UB may be detected at compile time, and the code generation for that particular branch may result in meaningless code. However, the not-so-conditional jump must skip all this and go straight past the closing }

(This question is not a duplicate because the compile-time detection of run-time UB was not covered earlier)

MSalters
  • 173,980
  • 10
  • 155
  • 350
  • That's interesting. Why is the compiler not allowed to randomly trash the program once it encounters a single instance of UB? – sharptooth Nov 24 '10 at 09:53
  • 1
    Undefined behavior is a run time property with potentially non causal effect. It has to be in the execution path for it to have an effect (there is a wide class of UB which is data dependent, for instance a[i] = a[j]++). – AProgrammer Nov 24 '10 at 12:23
2

A particular compiler (unless buggy) will always have the same behaviour (definitely no random code) on encountering such constructs (unless the context of the code is different).

In practice, "Undefined behaviour" means "different compilers will handle things differently".

If you want to know "will your imaginary compiler still conform to C++ standards?" - the answer I think is Yes.

  • 1
    Could not a compiler processing code for which behaviour is undefined enter that code into its AST, pass it through various processing and optimisations, and depending on surrounding code, optimisation levels, compiler flags etc. produce machine code that behaves differently, or affect surrounding otherwise well-defined code such that if behaves differently? I'm not saying it's especially likely, but do you have a basis for drawing such a definite conclusion to the contrary...? – Tony Delroy Nov 24 '10 at 11:38
  • Hi... I did say "unless the context of the code is different". The asker said - "emit ten totally random machine instructions into the produced machine code" which I think means "random code even when context is same". –  Nov 26 '10 at 10:29
  • Unfortunately a philosophy seems to have taken hold that compilers are entitled to assume that if receipt of certain input would inevitably cause Undefined Behavior, compilers should assume that such input could not possibly occur, and therefore eliminate code which would have no purpose but to handle such input. As a consequence, Undefined Behavior is not also unconstrained by the laws of time, but also by the laws of causality (e.g. given `if (x != 0) foo(); y=1/x;` a compiler may omit the conditional check before calling `foo`, since it would be under no obligation... – supercat Jul 13 '15 at 03:34
  • ...to refrain from calling `foo` when x is zero. – supercat Jul 13 '15 at 03:34
0

From the Draft Standard / http://www.kuzbass.ru:8086/docs/isocpp/intro.html / [1.3.12]

[Note: permissible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message). Many erroneous program constructs do not engender undefined behavior; they are required to be diagnosed. ]

Definitely doesn't list inserting random instructions, and it's hard to argue that the "ranges from" aspect would include a decision to insert random instructions as being anywhere on the continuum between the listed behaviours. ;-)

Tony Delroy
  • 102,968
  • 15
  • 177
  • 252
  • Hmm... There's "in a documented manner" - I guess that could allow random instructions. But then I can't see how it is different from implementation-defined behavior. – sharptooth Nov 25 '10 at 07:45
  • Anyway I asked a question on that - http://stackoverflow.com/questions/4274763/what-does-the-note-in-undefined-behavior-paragraph-in-c-standard-mean – sharptooth Nov 25 '10 at 08:10