
RFC: Automatic variable initialization - ndesaulniers
http://lists.llvm.org/pipermail/cfe-dev/2018-November/060177.html
======
captainmuon
It's a pity the flag -ftrivial-auto-var-init=zero is eventually going to go
away (there is -enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-
from-clang). I understand their motive, but it would be great to use that flag
and others like -fno-strict-aliasing etc. to make a "safe and friendly C"
dialect. I.e. turning undefined behavior into "obvious" behavior when
possible.

~~~
dlivingston
I thought you writing `-enable-trivial-auto-var-init-zero-knowning-it-will-be-
removed-from-clang` was just satire. Nope. A little humorous that it's a real
flag.
[https://reviews.llvm.org/D54604?id=174471](https://reviews.llvm.org/D54604?id=174471)

------
kazinator
Already in Lisp for decades: (let (x y z) (list x y z)) -> (nil nil nil).

However, nil has a distinct type. Thus:

    
    
      (let (x)  ;; not initialized
         ;; ...
         (when condition
           (setf x ...))
         (numeric-code x)) ;; still blows up if condition was false
    

In other words, this initialization doesn't create a big risk of hiding errors
due to initialization with a correctly typed bogus value that could be
inappropriate.

 _nil_ is the empty list. The risk of a bug where a local variable holds an
empty list that should have been initialized to some non-empty list seems low.

 _nil_ is also Boolean false. The risk of a bug where a local Boolean variable
was implicitly initialized to false, but should have been true, also seems
low.

------
saagarjha
Even if projects choose not to adopt this (~3% performance impact might be too
much?) I'd love to have this as a sort of "lightweight address/UB sanitizer"
to check for uninitialized variables.

~~~
AndyKelley
It actually accomplishes the opposite; hiding uninitialized values from tools
such as Valgrind. If you're trying to find uninitialized variables then you
would specifically _not_ enable this flag so that the detection can work.

This is why I intentionally leave variables uninitialized rather than put
bogus initialization values. Example:

    
    
        int x;
        if (cond) {
            x = foo();
        } else {
            x = bar();
        }
    

Some people when they see my code, have the urge to modify it so that x is
initialized to 0 before the branches. But this hides bugs. If for example, I
later made the if-else chain more complicated, and one of the branches failed
to initialize `x`, better to find out with Valgrind than to have a hard-to-
find-bug where an invalid value of 0 was used in an unexpected place.

This would be a flag to enable on release builds; a bug mitigation technique
rather than a debugging technique.

~~~
maxxxxx
The debug builds in VC++ used to initialize memory with a certain pattern.
That was pretty useful to see problems in the debugger.

I think in general a defined default value is a good thing. Maybe it shouldn't
be 0 but something like INT_MIN so you clearly see what something is wrong.

~~~
kazinator
That approach is great for uninitialized pointers, but not so hot for numeric
code.

~~~
maxxxxx
It's still good to see that all uninitialized ints are something like 12345678
instead of random numbers. Not perfect but helpful.

~~~
kazinator
True! trivial_object.ref_count is 0xDDDDDDE. Oops!

------
rurban
Sure, but why the trivial prefix? Doesn't sound too ensuring then.

~~~
saagarjha
I'm assuming the "trivial" refers to "trivial" types.

~~~
loeg
Sure, but it's unclear what the benefit of leaving auto C++ objects
uninitialized is.

~~~
eridius
IIRC, auto C++ objects aren't uninitialized, they're default-initialized, but
said default-initialization may leave them with uninitialized fields. I would
hope that this new automatic variable initialization would also apply to those
fields of default-initialized auto C++ objects.

~~~
kazinator
Built-in types like int are also "object"; only C++ _class_ objects can have
constructors that initialize them.

