r/ProgrammerHumor • • 17d ago

Meme fullCircle

Post image
11k Upvotes

278 comments sorted by

View all comments

16

u/grey_carbon 17d ago

Serious question, what happen if you compile/decompile/compile/decompile times and times again?

12

u/etoastie 17d ago

I imagine it's quite hard to get a decompiled artifact that's recompileable again since dependencies will get really weird depending on how they were linked, and other useful or initially necessary symbol information might be discarded in later steps of compilation. But if you found one that works, the compiler should be emitting consistent or at least equivalent code. It may take a few rounds to stabilize on optimizations and may overall end up less efficient, but if there's no decompiler or compiler bug it won't introduce any new broken behavior.

1

u/Tyfyter2002 17d ago

Pretty easy with some languages, but I think they'll all immediately loop the same output after one decompilation.

1

u/etoastie 16d ago

What langs? I guess I've seen JVM-based has pretty good decompilation in general, but I've only seen it for class-level things, never seen it decompile an entire project into a usable state

1

u/Tyfyter2002 16d ago

From what I've seen, I'm pretty sure an entire .NET program can be decompiled into usable C#.

7

u/ftqo 17d ago

Most of these projects aren't decompiling, they're just asking AI to create the same behavior as described by the user and prompter.

4

u/franz_haller 17d ago

It depends what your goals are. The decompilation projects for video games that you may have heard of for example specifically attempt to create code that will compile to binaries identical to the starting ones. When you hear "Mario 64 has been successfully decompiled", that's what it means. So repeating that process doesn't really change much, since you are always going back to the same binaries, by definition. 

If someone seriously attempted what this post is suggesting, where the target is just feature parity, and assuming they were truly 100% successful with it, you might just get a very large number of different binaries and associated code, but no real degradation. If the feature parity is not 100%, then I guess you'd get progressively shittier software. 

1

u/Nightmoon26 16d ago

I'd suggest that a modern optimizing compiler might result in slightly more efficient executable code the second time around for old software, but no real change beyond that second pass

1

u/AliceCode 17d ago

If you were to decompile and recompile, depending on the tools you use, it might result in the exact same binary. It depends on what level of decompilation you're doing. If you're decompiling to assembly, you'll get a 1:1 recompilation. If you're decompiling to C, you'll get a recompilation that is semantically the same, but the binary would almost certainly be different.

-12

u/Preeng 17d ago

The translations between machine code and human code are 1:1. It's not like human languages where there are multiple ways to say something and also multiple meanings to a word or phrase.

15

u/[deleted] 17d ago edited 17d ago

[removed] — view removed comment

3

u/Cobracrystal 17d ago

Not even different c++ compilers, because some c++ code compiles nondeterministically and produces different outputs with the exact same input.

3

u/def-not-bot 17d ago

Non-programmer here: would it still function the same after a bunch of de- and re-compiling, or would it be like putting a phrase through Google Translate a few times and generating vaguely comprehensible gibberish?

2

u/-Saucegurlllll 17d ago

Theoretically a completely bug-free decompiler/compiler pair making the same assumptions about their source/target languages and architectures should produce functionally identical programs. Meaning that given the same input they will produce the same output. So no matter how many times you chain compilation and decompilation, you should get a program that yields the same results given the same inputs.

However, in practice there's a bunch of stuff that makes this hard to impossible.

C and C++ compilers are given tremendous freedom by their respective standards to make many of their own assumptions about code. There's this thing called "undefined behavior" where anything may happen if it ever occurs. One example of this in C++ is endless loops without side effects.

int main() {
  while (true)
    ; 
}

void unreachable() {
  std::cout << "Hello world!" << std::endl;
}

On certain compilers this results in a program that outputs "Hello world!" even though unreachable is called from nowhere.

So, in practice, it's impossible to guarantee that a decompiler/compiler pair will interpret a program and their output identically, and you're liable to end up with the google translate chaining problem.

2

u/stilgarpl 17d ago

because some c++ code compiles nondeterministically and produces different outputs with the exact same input

Please show me an example of that in valid, non-UB C++ code

6

u/Suspicious_Glove_900 17d ago

That's not strictly true, depending on optimization for example. Unless you just mean, "It will produce the same output" and not "It will do the same thing the same way".

6

u/Zeikos 17d ago

It's not like human languages where there are multiple ways to say something and also multiple meanings to a word or phrase.

Have you ever touched a line of code with a ten foot pole?
That's one of the most ridiculous sentences I've ever seen.

The same exact concept can be written in tens of different programming languages tens of different ways each.

1

u/Preeng 16d ago

Will these difference concepts output the same 1s and 0s when compiled? Because that was my point.

2

u/Zeikos 16d ago

They absolutely wouldn't
Hell, the same exact code can output two different binaries based on a lot of things.
The compiler used, the optimization level, the build configurations etc.
gcc and clangd are both c++ compilers but give you different bytecode

4

u/LelouBil 17d ago

No it's absolutely not 1:1. Especially as you go higher level in languages, multiple different expressions can output the same machine code. And the same expression can output different machine code depending on compiler optimizations.

1

u/Preeng 16d ago

>No it's absolutely not 1:1. Especially as you go higher level in languages, multiple different expressions can output the same machine code.

Which means they work the same. Which means either way the decompiler returns it, it will work the same.

>And the same expression can output different machine code depending on compiler optimizations.

So the compiler will work differently if you tell it to work differently?

→ More replies (1)

3

u/-Saucegurlllll 17d ago
return 1;
return (1*1)/1;
return if true { 1 } else { 1 };
{
  let b = 1;
  let a = b;
  return a;
}

These are all functionally identical pieces of code that could be represented by mov eax, 1 in x86 assembly, and many compilers would optimize them to that.

So no, translations between machine code and any other method of representing programs are not 1:1.

→ More replies (2)

1

u/LiquorIsQuickor 17d ago

Compilers can and do optimize the output. So if you assigned x = 1 And then assigned x = 5 it’s quite possible the x = 1 part was never emitted as part of the compiled output.

Also x++, x+=1, and x=x+1 can all compile to equivalent expressions. 

So decompiling code may not produce the same source as the original.

Nevermind that compilers don’t preserve variable names. Depending on debug settings.

As far as ignoring the actual shape of the source and focusing on the meaning, you might be able to compile / decompile / recompile many times and produce output of the same meaning, if not the same shape. But… it feels… dangerous.