3 ms·
Did you read the article? In C, the compiler is perfectly allowed to compile "return x - x" with x uninitialized into "return 1". Accessing an uninitialized va
by TheLoneWolfling 12y ago
Did you read the article?
In C, the compiler is perfectly allowed to compile "return x - x" with x uninitialized into "return 1". Accessing an uninitialized variable in C is undefined behavior. The compiler can do anything. Nasal daemons.
> Compilers optimise away significantly more complex things than initialising a variable twice.
Right, but there are cases where being required to initialize a variable to, say, 0, is not equivalent than being required to initialize a variable to <some arbitrary value>.
For instance, "if (x == 0) y = someExpensiveFunction();" with x being uninitialized. With the "must be initialized to a specific constant" this sort of thing cannot be optimized, whereas with "must be consistent" this can be compiled down to nothing.
- deleted 12y ago[deleted]
- masklinn 12y ago> Did you read the article? Of course. > In C, the compiler is perfectly allowed to compile "return x - x" with x uninitialized into "return 1". Accessing an uninitialized variable in C is undefined behavior. The compiler can do anything. Sure. The peephole optimiser will pretty certainly run first and remove the whole expression though. > For instance, "if (x == 0) y = someExpensiveFunction();" with x being uninitialized. With the "must be initialized to a specific constant" this sort of thing cannot be optimized, whereas with "must be consistent" this can be compiled down to nothing. You've noted yourself in an other comment that the arbitrary value may be 0, the compiler can make no assumption about what's inside x, so there's absolutely no way to optimise this away, whereas with a specified constant the compiler knows statically whether the test will or will not succeed.
- TheLoneWolfling 12y ago> The peephole optimiser will pretty certainly run first That's what I'm trying to avoid though. The whole "pretty certainly" thing. The compiler will "pretty certainly" do not optimize this. The compiler will "pretty certainly" optimize that. And then compiler versions change and people get bitten. Time and time again. You're misinterpreting what I'm trying to say w.r.t. uninitialized variables here, or perhaps I'm just being idiotic at explaining myself. In what I'm describing, the compiler can assume the value of x to be anything it wishes. It's just that, once the value is fixed, it must be fixed. Think of it this way: the compiler may choose any initial value of any variable it chooses. I'm proposing a language where a read from an uninitialized variable must be consistent with the uninitialized variable having been set to an arbitrary value (in range) before the first read from it. So compiling the static code {int x; return x;} into {return 0;} is perfectly allowed, as is compiling it into {return 42;}.
- Dylan16807 12y ago>The peephole optimiser will pretty certainly run first and remove the whole expression though. Which is pretty dangerous. RunCriticalCodeA(); if (x) { y = 3; RunCriticalCodeB(); } else { y = 4; RunCriticalCodeB(); } OtherCriticalCodeC(); Fail to initialize x and suddenly all that code is replaced with a return. Even the part outside the if, even the part before the if. Compilers already exist that are this aggressive.
- TheLoneWolfling 12y agoYep. Optimization by C compilers has gotten to the point of "your worst enemy is the compiler". (My favorite: I had UB in my debug function, but inside an ifdef debug block for speed purposes. So I was getting the most absurd magic errors, that only happened when I was trying to debug) As I've said, I want reads from uninitialized variables to be at least consistent. if (x) { foo(); } else { foo(); } should always run foo(). Ditto: foo(); if (x) bar(); baz(); should always run baz() (assuming everything before it is "normal" - not going to get into jumps or system exit here), should always run foo() if it runs baz(), and should always run foo().