views:

157

answers:

6

Is a standard-conforming C++ implementation allowed to implement some behavior that is said to be implementation-defined in the standard in such way that it is different between different runs of the same compiled once program with the same input data?

For example, is an implementation allowed to say "the behavior is this on weekends and that otherwise" and implement behavior according to such statement?

+4  A: 

Implementation defined behavior means

Unspecified Behavior where each implementation documents how the choice is made

It is mandatory for the compiler writers to document the behaviour of a particular programming construct for a particular implementation.

.....in such way that it is different between different runs of the same compiled once program with the same input data?

Nopes!

For example, is an implementation allowed to say "the behavior is this on weekends and that otherwise" and implement behavior according to such statement?

I am not sure but I think the answer is no.

Prasoon Saurav
I don't see why this is not allowed. The standard says "how the choice is made", not "which one choice is made".
sharptooth
As I see it, the definition of implementation-defined behaviour given doesn't rule out the possibility of run-to-run differences, provided that it documents exactly when each case occurs and exactly what happens for each one.
j_random_hacker
@sharptooth: I have edited my answer, but I am almost certain certain that the answer to the your first question is NO. For example considering `sizeof(int)`, it is guaranteed(as the implementation has documented the behaviour) to remain fix for a particular implementation. .... I am a bit confused by `and implement behavior according to such statement?`
Prasoon Saurav
A conforming implementation can quite easily state that `sizeof(int)` is 4 on weekdays and 2 on weekends. It's no different to stating it will be 2 if you define `INT_IS_2_BYTES` or 4 otherwise. As long as it's documented, it's fine. And the "4 on weekdays, 2 otherwise" statement is _entirely_ consistent - the _numbers_ don't have to be consistent, just the _specification_. Of course, having said that, I'd steer clear of a compiler that actually did this :-)
paxdiablo
I think you have to clarify when you suspect the change. The behavior will not change between 2 runs of the compiled program. It may however change if you compile a program twice (e.g. with different compiler settings).
Tobias Langner
@paxdiablo: Ah! Thats why I said I was not sure about the answer to his second question :). But still I don't understand Johannes' answer to the first question. See my comment under his post.
Prasoon Saurav
@paxdiablo: I'd say that would match the wording, but not the intent of the standard.
peterchen
@paxdiablo: Could a compiler legally specify that an 'unsigned int' in memory is 16 bits, but in certain circumstances, in the absense of typecasts, intermediate calculations with 'unsigned int' will not be longer? E.g. could a compiler specify that (ui1 + ui2) >> 1 will yield an arithmetically-correct rounded-down average? I think it could for 'int', but could it for 'unsigned int'?
supercat
A: 

rand(3) in <stdlib.h> can be called from within C++, not sure how much of the C library is included in "standard C++", but surely there's some standards-conforming mechanism to generating random numbers.

time(3) in <time.h> returns the current time; same story with C++ and calling into the C library.

sarnold
how is this relevant to the question?
Naveen
Are `rand()` or `time()` labelled implementation-defined? I can only assume that they are, and if so they would indeed be a counterexample. Well, unless you consider the current time and/or system RNG state to be part of the input.
j_random_hacker
@naveen, I assumed `rand()` is specified in the standard but the details are implementation-defined. I'm having trouble verifying this assumption.
sarnold
+6  A: 

Of course, if the implementation documents when exactly the behavior changes with different runs, that's fine. Notice that the implementation-defined behavior is part of the parameters of the abstract machine:

The semantic descriptions in this International Standard define a parameterized nondeterministic abstract machine.

Certain aspects and operations of the abstract machine are described in this International Standard as implementation-defined (for example, sizeof(int)). These constitute the parameters of the abstract machine. Each implementation shall include documentation describing its characteristics and behavior in these respects. Such documentation shall define the instance of the abstract machine that corresponds to that implementation (referred to as the ‘‘corresponding instance’’ below).

This does not allow changing the behavior in a single run of the compiler. But between different runs of the compiler, the compiler may use a different corresponding abstract machine which differs by different implementation defined values, according to what the implementation defined. Command line parameters like -Wall (which changes the implementation-defined set of diagnostic messages) are the most common example of this. This is a difference to unspecified behavior in addition to the documentation requirements. Unspecified behavior is much less restrictive:

Certain other aspects and operations of the abstract machine are described in this International Standard as unspecified (for example, order of evaluation of arguments to a function). Where possible, this International Standard defines a set of allowable behaviors. These define the nondeterministic aspects of the abstract machine. An instance of the abstract machine can thus have more than one possible execution sequence for a given program and a given input.

Johannes Schaub - litb
`...define a parameterized nondeterministic abstract machine. ` As the abstract machine is nondeterministic how is it necessary for a behavior to be consistent in a single run of the compiler?
Prasoon Saurav
@Prasoon, only some paths - those where behavior is unspecified - introduce non-determinism. For example, the regular expression `z(a|b)` can be expressed by a non-deterministic finite state machine (NFA) that matches either `a` or `b` at the end of input. But still, it consistently matches `z` at the start of input :) Now for implementation-defined behavior, if the parameters (say, `z` at the start) would change, you would get a different corresponding abstract machine resulting. You would not anymore have a single implementation translate the source code, but two. :)
Johannes Schaub - litb
Ah!! And sharptooth's question mentions that the input data is required be the `same`....Phew! thanks Johannes:)
Prasoon Saurav
+1  A: 

IIRC, system() is required to exist, but given implementation defined behavior. Something like system("ls | grep foo") will naturally have different effects based on whether or not your system can execute something called ls, which might vary between runs. And, even on a fairly normal UNIX machine where ls and grep do what you would expect and aren't taken out, the result will still depend on the existence of a file with foo in the name, which will certainly be allowed to vary over time, and from where the program is executed, etc. It just depends on where you draw the line of "the same input data." If the machine is in a perfectly identical state then you can expect identical behavior, but no two runs will involve a machine truly in a pedantically identical state. (Even the temperature of the CPU in otherwise perfectly identical machines could result in some throttling behavior, which alters the winner of some race condition, which visibly results in different behavior of your program.)

wrosecrans
+3  A: 

One example I can think of is if the program uses big or little endian representation for numbers. I believe that this would certainly count as implementation defined behaviour.

On some chips, for example certain ARM chips it's possible to switch modes at run time so you might want a compiler which could produce a program that would run in either mode meaning that you have implementation defined behaviour which could potentially be different on each run depending on external settings.

Similarly I guess you could write a compiler which produced both 32 ad 64 bit compiled of the same program - and the mode it executed could be determined at run time. Again, the documentation would have to say that ints were 32 bit or 64 bit depending on how you ran it.

To be honest I can't see anyone doing either of these things, but they both sound vaguely plausible examples of what you were asking for and I can't see why they wouldn't be legal under the standard as long as the documentation properly documented the nature of the system dependent behaviour.

John Burton
+1, In MacOSX universal binaries contain both a 32 and 64 bit version (in the latest MacOS X versions that have 64bit support) and you can choose at launch time which version you want to run. The binaries can even contain code for a completely different architecture as PowerPC. And in case you wonder, it is useful. There are some safari plugins that fail to run in 64bit, so you can start a safari session in 32bit when you need them.
David Rodríguez - dribeas
Ah nice, I wasn't aware that MaxOSX did this :)
John Burton
+1  A: 

The guarantees are what the compiler has documented. Different compiler flags or different state of the computer at compile time might affect how the compiler/optimizer processes your program and that can have an effect on the result. With compiler flags having the greatest impact (the same compiler can be used to generate 32 and 64bit programs in a 64bit environment, in the two runs alignment requirements can differ).

You can expect that in most cases the implementor will provide some basic guarantees about the behavior of the implementation and the program it generates for a given set of compiler/linker parameters. Even if the load of the system can affect how much the optimizer can work on your program --some optimizers will be allocated some limited time-- that should not change the expected behavior.

Note that while there is no guarantee, it would be hard to market a compiler that produces code with different behaviors depending on unrelated parameters as the position of the moon relative to the stars.

David Rodríguez - dribeas