RFC-0x000 - Should (automatic) local variables be initialized to 0 for the programmer?

RFC-0x0000

For clang release mode compiles:

Should (automatic) local variables be initialized to 0 for the programmer?

local_var_test_RFC0x0000.tar.gz (9.7 KB)

No.

I believe that you are confusing several issues here. First, you are assuming that GCC is initializing local values to 0. This is absolutely and categorically not the case. Take this trivial test as an example:

$ cat stack.c
int stack(void)
{
  int a;
  printf("%d\n", a);
  a = 12;
  return a;
}

int main(void)
{
  stack();
  return stack();
}
Liberator:tmp theraven$ gcc stack.c && ./a.out
0
12
12

As you can see, a is initialized to 0 the first time stack() is called, but not the second time? Why is this? Because the memory for the stack is acquired from the OS. As a security precaution, to prevent information leakage between processes, memory acquired from the kernel is initialized to 0 before being handed to the userspace program. This means that the entire stack is initially 0.

In this function, however, the second time that it is called, the first call has already written a value of 12 to that stack slot, so reusing it you find that the old value is already there. If you had called another function in the middle, then this would not be the case - its on-stack values would be there instead.

Secondly, you are assuming that the fact that GCC assumes the stack values to be 0 but they are not is an insidious bug. It is not, it is a side effect of undefined behaviour.

Uninitialized variables have an undefined value. This means that the optimizer is free to assume that they have any value that it wishes. It may assume that the value is 0, 123, or any other value that would produce faster code. It does not matter, from the point of view of standards conformance, whether this assumption is correct, because the result of comparing a defined value to an undefined value is, itself, undefined and so any behaviour is valid.

Finally, setting all locals to 0 initially would incur a speed penalty, which is the last thing that you want in release code. You don't need the static analyser to tell you that you are doing something stupid - both clang and GCC can issue a warning if you use a variable before initializing it.

David

-- Sent from my Difference Engine

Hi!

I'm trying to build Clang for Windows.
Once I succeeded but it fails.

cmake said:

CMake Error at cmake/modules/LLVMProcessSources.cmake:50 (message):
   Found unknown source file
C:/Home/takei/Job/TMC-ATG/atgtool/llvm/lib/CodeGen/PostRAHazardRecognizer.cpp

   Please update
   C:/Home/takei/Job/TMC-ATG/atgtool/llvm/lib/CodeGen/CMakeLists.txt

Call Stack (most recent call first):
   cmake/modules/LLVMProcessSources.cmake:25 (llvm_check_source_file_list)
   cmake/modules/AddLLVM.cmake:5 (llvm_process_sources)
   lib/CodeGen/CMakeLists.txt:1 (add_llvm_library)

Is PostRAHazardRecognizer.cpp simply added to the CMakeLists.txt?

Thanks!

cmake_log.txt (5.51 KB)

This was fixed in r105987.

- Michael Spencer

I mistakenly did not post my reply to David to the list as well…
Please examine this issue in terms relating to gcc compatibility… Thanks
Daniel

I mistakenly did not post my reply to David to the list as well...
Please examine this issue in terms relating to gcc compatibility... Thanks
Daniel

*From:* dan chap <dchapiesky@yahoo.com>
*To:* David Chisnall <theraven@sucs.org>
*Sent:* Mon, June 14, 2010 6:35:12 PM
*Subject:* Re: [cfe-dev] RFC-0x000 - Should the code generator _enforce_
assumptions of the optimizer in Clang release mode? PREVIOUSLY Should
(automatic) local variables be initialized to 0 for the programmer?

David,

"As a security precaution, to prevent information leakage between
processes, memory acquired from the kernel is initialized to 0 before
being handed to the userspace program. This means that the entire stack
is initially 0"

is not applicable to all platforms nor the lli JIT environment.

My original post shows test results from all of the various modes of gcc
and clang on ubuntu x86.

Please review the attached test code and shell script.

I realized after my initial post that the true question here is:

-------------------------
*** Should the code generator _enforce_ assumptions of the optimizer in
Clang release mode?
-------------------------

The assertion "This means that the optimizer is free to assume that they
have any value that it wishes. It may assume that the value is 0, 123,
or any other value that would produce faster code. It does not
matter." cannot be applicable unless the runtime behaviour is as
expected and.....

Have you tried declaring a pointer?
It is not initialized to NULL, it is 0x4 for me for example.

A) the test program I submitted _shows_ gcc release mode functioning
_as_expected_ and Clang release/debug/etc... __failing__ to produce
accurate runtime behaviour.

You already have undefined behaviour with gcc: -O0 doesn't init to 0 (if
you run it under valgrind you'll see a lot of warnings), the fact that
with release mode they happen to be 0 is just a coincidence.

GCC doesn't guarantee that it will init local vars to 0 when you
optimize, and in fact it doesn't.
In fact if you run GCC with -Wall it'll warn you that your local vars
are not initialized.

If you are worried that some nonconforming code will be miscompiled, you
can use -Werror=uninitialized, that'll make sure that you are not using
uninitialized values, and if you are your program will fail to compile.
The correct thing to do is to fix those programs
(although -Wuninitialized has some false positive warnings when the
variable is initialized on all code paths before use, gcc just can't
determine that).

B) the initial question I had was: should this behaviour be to extend
compatibility towards gcc?

clang's -Wuninitialized should warn about these cases, thats all the
compatibility that is needed.

Best regards,
--Edwin

Hi!

I wonder what list I've to tell (llvm-dev?), but ...

StringMapImpl::init() calls 'calloc()',
but I can't find any 'free()' that should be paired.
Missing?

Thanks

It's free'd in the destructor of StringMap (include/llvm/ADT/StringMap.h:418).

Oops...
I do find it. Thanks and sorry for the noise :slight_smile:

> Hi!
>
> I wonder what list I've to tell (llvm-dev?), but ...
>
> StringMapImpl::init() calls 'calloc()',
> but I can't find any 'free()' that should be paired.
> Missing?

It's free'd in the destructor of StringMap

(include/llvm/ADT/StringMap.h:418).