0

There are some undefined behavior examples in C/C++ which I was trying on my computer in order to see whether they indeed gave different results each time I ran the code. I noticed that within the same compiler, all the runs gave the same result. So my first question is, is this really undefined behavior?

The second question: How come when I change my compiler from clang to vs, the results change? What can be the root cause of this?

Example 1:

    #include <stdio.h>

    int main (int argc, char *argv[])
    {

      int i = 1;
      int v = 2;
      i = i++ + v;
      printf("%d\n", i);

      return 0;
    }

In Clang and gcc the result is always 3. While in vc, the result is always 4.

Another example with integer overflow:

int main (int argc, char *argv[])
{

  int i = 1;
  int v = 2;
  i = i++ + v;
  printf("%d\n", i);


  return 0;
}

Clang gives always a totaly diferent result (which I consider as undefined behavior) while gcc always give the same result -2147483648.

I expect the results to vary depending on which machine they use (for example 2 complement) not to vary between compilers.

So my questions in a nutshell: 1) what is ment by undefined behavior and 2) how come the results differ from compiler to compiler?

Robbe Claessens
  • 79
  • 1
  • 1
  • 6

2 Answers2

4

is this really undefined behavior?

Until C++17 yes, the behaviour is undefined. Since C++17, the behaviour is well defined.

How come when I change my compiler from clang to vs, the results change?

What can be the root cause of this?

2) how come the results differ from compiler to compiler?

Because the behaviour of the program is undefined.

Since C++17, the correct behaviour is to output 3. If a compiler produces different behaviour, then it does not conform to C++17 (you may need to enable C++17 conformance explicitly).

1) what is ment by undefined behavior

It means that the program can have any and all or no particular behaviour, and that behaviour isn't in any way constrained by the standard.


I noticed that within the same compiler, all the runs gave the same result.

Note that this is not guaranteed when behaviour is undefined.

Also note undefined behaviour does not guarantee that all runs don't give you the same result.

There wouldn't even be a guarantee that you get any result.


I expect the results to vary depending on which machine

Note that undefined behaviour does not guarantee that the result would vary depending on machine.

not to vary between compilers.

There is no guarantee that undefined behaviour won't vary between compilers.

In case it wasn't clear: Nothing about the behaviour of the program is guaranteed when it is undefined.

eerorika
  • 232,697
  • 12
  • 197
  • 326
  • 1
    might be worth mentioning that c++17 defines this code. – cigien Apr 02 '20 at 20:47
  • @cigien Good point. – eerorika Apr 02 '20 at 20:50
  • So what is it called when a program its output may differs each run? In testing these are called flaky tests. How would you call such a programs? – Robbe Claessens Apr 03 '20 at 06:36
  • @RobbeClaessens `So what is it called when a program its output may differs each run?` you mean like a program that outputs the time of day in nanoseconds? – eerorika Apr 03 '20 at 09:40
  • @eerorika yes! But another example would be random number generator (with no seed for example). – Robbe Claessens Apr 04 '20 at 16:23
  • @RobbeClaessens Note that such random number generator cannot be implemented in software. Software can only produce pseudo random numbers, and there is no such thing as "no seed" for a pseudo random number. But indeed, program containing randomness has little to do with undefined behaviour. – eerorika Apr 04 '20 at 17:06
2

which I was trying on my computer in order to see whether they indeed gave different results each time I ran the code.

That's not the definition of undefined behavior.

what is meant by undefined behavior?

Undefined behavior happens when some condition is not covered by the standard or the standard explicitly reports it as undefined behavior. In such a case, the compiler is allowed to do whatever it wants. Since compilers are deterministic programs though, using the same version of the same compiler on the same environment to compile the same code will most likely cause the same result. That's completely "normal". Undefined behavior does not mean that the output will change every execution, though it most definitely could.

See the definition of "undefined behavior" at paragraph J.2, page 492 of the C99 Standard here for more information.

how come the results differ from compiler to compiler?

Since, by definition, undefined behavior does not apply any restriction or mandate any particular behavior, any compiler is free to interpret the source code however it wants, and produce whatever result it wants. This is the number one reason why undefined behavior is a very dangerous beast. Even different versions of the same compiler could behave differently.

Compilers usually assume undefined behavior to never happen, and therefore make assumptions about the program to be able to better optimize it, or even to be able to emit code at all. Causing undefined behavior can break those assumptions and cause the compiler to emit completely different code than whatever the programmer had in mind.

Marco Bonelli
  • 63,369
  • 21
  • 118
  • 128
  • The annex describes general constructs which would invoke Undefined Behavior in some circumstances, but the actions only invoke UB in the specific circumstances described in the cited sections. Further, the authors of the Standard, UB "identifies avenues of conforming language extension", but the question of when implementations should extend the language in such fashion is a Quality of Implementation issue outside the Standard's jurisdiction. – supercat Apr 07 '20 at 20:54