Does the gcc output of the object file (C language) vary between compilations? There is no time-specific information, no change in compilation options or the source code. No change in linked libraries, environmental variables either. This is a VxWorks MIPS64 cross compiler, if that helps. I personally think it shouldn't change. But I observe that sometimes randomly, the instructions generated changes. I don't know what's the reason. Can anyone throw some light on this?
-
Please elaborate: Does your source code remain the same each time? Do other linked libraries change? Is time-specific information making its way into the source (like build time or a VCS revision #)? Could you post an example that can reproduce the issue? – Michael Foukarakis Feb 27 '13 at 10:48
-
Are you sure the changes are in actual valid instructions? It's possible that some section contains uninitialized bits, perhaps because GCC "knows" those bits don't matter. The state of uninitialized bits can of course vary randomly between runs of the same program, on the same input. – unwind Feb 27 '13 at 10:52
-
@MichaelFoukarakis: No, no timestamps in the code. The libraries remain the same. Already mentioned in the title that source doesn't change. – Arun Kumar M S Feb 27 '13 at 11:22
-
@unwind: I disassembled the object file and saw the difference in machine instructions. Not related to random bits. – Arun Kumar M S Feb 27 '13 at 11:23
-
1@arun: Can you map the machine code that's changing between compilations back to the source code from which it was generated, and show us those source lines? I'm going to speculate that you're invoking undefined behavior in the source code. – John Bode Feb 27 '13 at 12:02
-
@JohnBode: @JohnBode: Unfortunately, I'm not allowed to share any part of the source code (even the snippet!). But I can tell you that it involves copying a IPv6 address. Something like: `st1->addr6[0] = st2->addr6[0]; st1->addr6[1] = st2->addr6[1]; st1->addr6[2] = st2->addr6[2]; st1->addr6[3] = st2->addr6[3];`. Since this is MIPS64, there are lot of lw, sw operations to do this. In one instance of compilation, it is generated as 'move v0, v1'. In another it is output somewhat like `lw v0, 28`. – Arun Kumar M S Feb 27 '13 at 13:21
-
1@arun: Hmmm. Well, I can only think of two possibilities. First is that you have invoked undefined behavior somewhere around that code, if not within those lines themselves. Second is that you may be hitting an obscure bug within the compiler. I think the first case is far more likely, but I've hit obscure compiler/linker bugs before, so I can't dismiss the second out of hand. – John Bode Feb 27 '13 at 15:30
-
1@JohnBode, "undefined behaviour" is just a shorthand for "the compiler is allowed to assume this won't happen, so it can let anything whatsoever happen here", it doesn't mean the compiler will generate different code each time (I'd hope not...). – vonbrand Feb 27 '13 at 17:08
-
@vonbrand - it depends on the behavior being invoked. No, I don't have an example; I can't even come up with something contrived off the top of my head. The same source *should* be interpreted the same way from run to run, and even code that invokes undefined behavior *should* invoke the *same* behavior from run to run if nothing else changes. But I can't guarantee that. Like I said, the alternative is a bug in the compiler itself. – John Bode Feb 27 '13 at 19:02
-
@JohnBode, even a compiler bug should give the same results each time. – vonbrand Feb 27 '13 at 19:06
-
=thwacks forehead= @arun is the build always being run from the same machine as the same user, or are you building from more than one machine or under more than one user? – John Bode Feb 27 '13 at 19:16
-
@JohnBode: the same machine and the same user. It is a vxworks 5.5 cross compiler running on windows XP 32-bit on a cloud VM. The compiler uses Cygwin tool chain internally. All these parameters stay constant between compilations. – Arun Kumar M S Feb 28 '13 at 05:58
-
Thank you stackoverflow members for quick and relevant responses. :) Really appreciate it! – Arun Kumar M S Feb 28 '13 at 06:15
-
I found an answer on - [stackoverflow](http://stackoverflow.com/questions/4140329/binary-object-file-changing-in-each-build). I've not tried it myself though. – syam Dec 03 '15 at 18:31
-
Yes, this is a thing our team has experienced - and indeed with MIPS cross-compilers it was. The typical scenario was such that with certain compilation units there were two possible outcomes of compilation, selected randomly. The assembly analysis showed that they were full functional equivalents, and most often the difference was in some non-interdependent instructions being swapped. This behavior was only observed with optimizations turned on. Note: this was not related to `-frandom-seed`, the source code didn't depend on that. – ach Jun 26 '16 at 13:42
5 Answers
How is this built? For example, if I built the very same Linux kernel, it includes a counter that is incremented each build. GCC has options to use profiler information to guide code generation, if the profiling information changes, so will the code.
What did you analyze? The generated assembly, an objdump of object files or the executable? How did you compare the different versions? Are you sure you looked at executable code, not compiler/assembler/linker timestamps?
Did anything change in the environment? New libraries (and header files/declarations/macro definitions!)? New compiler, linker? New kernel (yes, some header files originate with the kernel source and are shipped with it)?
Any changes in environment variables (another user doing the compiling, different machine, different hookup to the net gives a different IP address that makes it's way into the build)?
I'd try tracing the build process in detail (run a build and capture the output in a file, and do so again; compare those).
Completely mystified...

- 11,412
- 8
- 32
- 52
-
"How is this built? For example, if I built the very same Linux kernel, it includes a counter that is incremented each build. GCC has options to use profiler information to guide code generation, if the profiling information changes, so will the code." --> No profile / debug information; -O2 enabled. – Arun Kumar M S Feb 28 '13 at 06:02
-
"What did you analyze?" --> generated the objdump and compared. The difference was in a machine instructions in a function. I'm only compiling a static library, so no executable... I analysed on the static library. I'd ignore the timestamps if it was so. The difference was clearly machine instructions. No environmental changes. In my use case, it is unthinkable to change kernels between two compilation. There is no such need. I'm building a library for a embedded system through a cross compiler. I also tried to compare the build log. There is no difference. – Arun Kumar M S Feb 28 '13 at 06:13
-
-
very strange indeed. I see another observation. When I compile by double-clicking a batch file there seems to be difference in the object code compared to calling the batch file directly from the command line. The batch file doesn't change, add or delete any environment variable. It also doesn't call another batch file. If I copy the contents of the batch file onto command line, there is no difference between successive compilation. I guess this has got something to do with the host OS (windows) or else because of a bad compiler install. Anyway thanks for answering. – Arun Kumar M S Mar 15 '13 at 06:19
-
@arun, perhaps you should have made clear that this is Windows. I thought it was Linux; with Windows (and CygWin, as you seem to be using?) I've got almost no experience, let alone in-depth insights. – vonbrand Mar 15 '13 at 13:20
I had a similar problem with g++. Pre 4.3 versions produced exactly the same object files each time. With 4.3 (and later?) some of the mangled symbol names are different for each run - even without -g or other recordings. Perhaps the use a time stamp or random number (I hope not). Obviously some of those symbols make it into the .o symbol table and you get a difference. Stripping the object file(s) makes them equal again (wrt. binary comparison). g++ -c file.C ; strip file.o; cmp file.o origfile.o

- 11
- 1
Why should it vary? It is the same result always. Try this:
for i in `seq 1000`; do gcc 1.c; md5sum a.out; done | sort | uniq | wc -l
The answer is always 1
. Replace 1.c
and a.out
to suit your needs.
The above counts how many different executables are generated by gcc
when compiling the same source for 1000
times.

- 20,967
- 7
- 57
- 109
-
-
-
ok, I tried such things. Our hypothesis that it shouldn't change indeed seems to be true. But for a code of large size , does the same hold true. Can the compiler generate one set of instructions at compilation 'c1' and then later generate a different output for compilation 'c2' but keeping the functionality same? – Arun Kumar M S Feb 27 '13 at 10:49
-
Not the same compiler, with the same flags. The idea of random compilation seems intriguing. – Mihai Maruseac Feb 27 '13 at 10:56
-
Hello Mihai, the compiler remains the same, I don't change the compiler. The idea that output changes randomly does seem strange. So, I wanted to know if internal GCC architecture chooses different optimisation stratergies at different times. Can it take lenience with the exact instructions as long as the functionality remains same between compilations? – Arun Kumar M S Feb 27 '13 at 11:26
-
@arun, the compiler is (I hope) a deterministic program. It should only generate different code when something changes. The question here is _what_ has changed, and _why_. – vonbrand Feb 27 '13 at 19:04
I've found that in at least some environments, the same source may yield a different executable if the source tree for the subsequent build is located in a different directory. Example:
Checkout a pristine copy of your project to dir1. Do a full rebuild from scratch.
Then, with the same user on the same machine, checkout the same exact copy of your source code to dir2 (dir1 != dir2). Do another full rebuild from scratch.
These builds are minutes apart, with no change in the toolchain or any 3rd party libs or code. Binary comparison of source code is the same. However, the executable in dir1 has different md5sum than the executable in dir2.
If I compare the different executables in BeyondCompare's hex editor, the difference is not just some tiny section that could plausibly be a timestamp.
I do get the same executable if I build in dir1, then rebuild again in dir1. Same if I keep building the same source over and over from dir2.
My only guess is that some sort of absolute paths of the include hierarchy are embedded in the executable.

- 789
- 1
- 11
- 25
My gcc sometimes produces different code for exactly the same Input. The output object files differ in exactly one byte.
Sometimes this causes linker Errors, because one possible object file is invalid. Recompiling another version usually fixes the linker error.
The gcc Version is 4.3.4 on Suse Linux Enterprise. The gcc Parameters are:
cc -std=c++0x -Wall -fno-builtin -march=native -g -I<path1> -I<path2> -I<path3> -o obj/file.o -c file.cpp
If someone experiences the same effect, then please let me know.

- 2,198
- 29
- 34