Let\'s pretend my program contains a specific construct the C++ Standard states to be unspecified behavior. This basically means the implementation has to do something reasonabl
Undefined behavior can vary between runs of the same program, and even between execution of the same code in the same run of the program. As an example, the value of an uninitialized (automatic) variable is undefined, and then its actual value is just whatever value that happened to be at that place in memory. Obviously, this can vary.
EDIT:
This goes for unspecified behavior too. For example, the order of evaluation of function arguments is unspecified, so if they have side effects, those side effects can occur in any order. This may print "Hi!Ho!" or "Ho!Hi!":
f( printf("Hi!"), printf("Ho!") );
This can vary between executions, too. As the standard says: "An instance of the abstract machine can thus have more than one possible execution sequence for a given program and a given input." The difference is that with undefined behavior, anything can happen: the computer can explode, reformat the disk, or whatever. If the behavior is unspecified, the computer is not allowed to explode.
There is also implementation-defined behavior, such as the value of sizeof(int)
. This must be the same at all times, for the same compiler.
It's worth noting that the implementation of the specified behaviour of the C++ Standard is not 100% identical across compilers, even today. Given this, it's not reasonable to expect that unspecified or undefined behaviour is compiler-agnostic. You have the best chance of writing portable code if you just stick to the Standard.
But can this behavior differ between compiles of the same program on the same compiler with same settings in the same environment?
Yes.
In other words, if I dereference a null pointer on line 78 in file X.cpp and the implementation formats the drive in such case does it mean that it will do the same after the program is recompiled?
The results of undefined behaviour are almost always caused by code emitted by the compiler interacting with the operating system and/or hardware in ways not specified by the language designer. So if you dereference a NULL pointer, what happens is really nothing to do with the compiler but will depend on how the underlying OS/hardware deals with an invalid memory access. If the OS/hardware always deals with this in a consistent manner (for example via a trap), then you could expect UB to be consistent, but this has nothing to do with the language or the compiler.
I don't know about unspecified behaviour (but judging from the name, maybe it does the same bad/evil thing everywhere just no one really knows what exactly it does). But for the undefined behavior, i think this one could behave VERY differently across platforms or compilers. I've seen some really strange coredumps on Solaris which did not occur on Ubuntu etc.
Unspecified and undefined behavior are not guaranteed to be consistent between separate runs of an already compiled program. That alone already makes the notion of consistency between separate compiles totally meaningless.
Also, it is probably worth adding that undefined behavior can manifest itself at compilation stage by preventing the program from compiling at all.
Many such behaviours are implemented differently when compiled with different optimization levels or with or without debug mode.