Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is the phrase: "undefined behavior means the compiler can do anything it wants" true?

Specifically in reference to: https://blogs.msdn.microsoft.com/oldnewthing/20140627-00/?p=633/

I'm a new C++ programmer and I'm currently learning about undefined behavior and its effects on a program. I was linked specifically to the above blog, which says that when undefined behavior occurs, anything can happen.

It mentions several times specifically that the compiler can allow anything to happen when undefined behavior occurs.

What specifically causes this to occur, and why does it happen?

like image 509
Yvain Avatar asked Feb 28 '18 15:02

Yvain


People also ask

What is undefined behavior in programming?

So, in C/C++ programming, undefined behavior means when the program fails to compile, or it may execute incorrectly, either crashes or generates incorrect results, or when it may fortuitously do exactly what the programmer intended.

Why does undefined behavior exist?

Undefined behavior exists mainly to give the compiler freedom to optimize. One thing it allows the compiler to do, for example, is to operate under the assumption that certain things can't happen (without having to first prove that they can't happen, which would often be very difficult or impossible).

What causes undefined Behaviour in C?

In C the use of any automatic variable before it has been initialized yields undefined behavior, as does integer division by zero, signed integer overflow, indexing an array outside of its defined bounds (see buffer overflow), or null pointer dereferencing.

Is there undefined behavior in Python?

Python has undefined behavior because it's implementations are written in languages that do.


2 Answers

Nothing "causes" this to occur. Undefined behaviour cannot "occur". There is no mystical force that descends upon your computer and suddenly makes it create black holes inside of cats.

That anything can happen when you run a program whose behaviour is undefined, is stated as fact by the C++ standard. It's a statement of leeway, a handy excuse used by compilers to make assumptions about your code so as to provide useful optimisations.

For example, if we say that dereferencing nullptr is undefined (which it is) then no compiler needs to ever check that a pointer is not nullptr: it can just assume that a dereferenced pointer will never be nullptr, and if it's not then any consequences are the programmer's problem.

Due to the astounding complexity of compilers, some of those consequences can be rather unexpected.

Of course it is not actually true that "anything can happen". Your computer has neither the necessary physical power nor the necessary legal authority to instantiate a black hole inside of a cat. But since C++ is an abstraction, it seems only fitting that we use abstractions to teach people not to write programs with undefined behaviour. If you program rigorously, assuming that "anything can happen" if your program has undefined behaviour, then you will not be surprised by said rather unexpected consequences, and you will not be tempted to try to "control" the outcome in any way.

like image 111
Lightness Races in Orbit Avatar answered Oct 24 '22 05:10

Lightness Races in Orbit


From the point of view of the C and C++ Standards, the fact that some situation invokes "Undefined Behavior" means nothing more nor less than that the Standard imposes no requirements on what an implementation must do in that situation in order to be conforming. It does not imply any particular judgment as to whether implementations intended for purposes on any particular platforms should be expected to behave predictably, nor whether predictable behavior in such a situation might be required to make an implementation suitable for a such purposes on such platforms.

For some reason, some compiler writers have equated "the Standard does not require X" with "there is no need for implementations to do X", without any particular regard for the purposes to which their compilers would be put, and without regard for what behaviors might be necessary to fulfill those purposes. What caused Undefined Behavior to digress to the "anything can happen" was that compiler writers interpreted it not as an acknowledgment that there may be some combinations of platform and application field where the cost of ensuring predictable behavior would exceed the benefit, and compiler writers should exercise judgment as to when that is the case, but instead as an indication that the authors of the Standard had already exercised judgment that on all combinations of platform and application field, the cost of ensuring predictable behavior would outweigh the benefits, and there's no need for compiler writers to exercise judgment because the authors of the Standard have already done so.

like image 38
supercat Avatar answered Oct 24 '22 05:10

supercat