4

When I compile the following C++ program I need to add the -O2 flag to get a warning about the uninitialized variable. Why is that?

unsigned long fac(unsigned long n)
{
  unsigned long product;

  while (n > 1)
  {
    product = product * n;
    n = n - 1;
  }

  return product;
}

➜  a g++ --version
g++ (GCC) 8.3.1 20190223 (Red Hat 8.3.1-2)

edit: To clarify the question, I did of course enable the warning.

choeger
  • 3,562
  • 20
  • 33

3 Answers3

4

The warning appears in the -O2 (or any other optimization) mode along with the option -Wmaybe-uninitialized turned on. The -Wmaybe-uninitialized option is also turned on with -Wall and with any of the optimization modes enabled.

The reason for this as per GCC documentation is:

-Wmaybe-uninitialized

For an automatic (i.e. local) variable, if there exists a path from the function entry to a use of the variable that is initialized, but there exist some other paths for which the variable is not initialized, the compiler emits a warning if it cannot prove the uninitialized paths are not executed at run time. These warnings are only possible in optimizing compilation, because otherwise GCC does not keep track of the state of variables. These warnings are made optional because GCC may not be able to determine when the code is correct in spite of appearing to have an error.

Then follows an example of how the above mentioned scenario can happen.

Community
  • 1
  • 1
P.W
  • 26,289
  • 6
  • 39
  • 76
1

To answer the why question in a bit more depth, this is done so chiefly to reduce false positive rate and compilation time. The pass that produces these warnings (the -Wmaybe-uninitialized flavor) is run very late in the compilation pipeline (see gcc/passes.def; the corresponding pass_late_warn_uninitialized pass is on the line 338 or so). GCC tries hard to produce as little false positives for this warning as possible. To do so, it needs more precise information about the program. To get this information it needs some analyses/transformations performed beforehand (for example, jump threading is particularly beneficial). And some of them are too expensive to be enabled at -O0.

GCC development is done in the open. All the major decisions are normally discussed on the mailing lists and in the bugzilla. See, for example, this comment.


Vladislav Ivanishin
  • 2,092
  • 16
  • 22
-1

An uninitialized variable is not a technical error; Memory in x86/x64 assembly can be uninitialized. Reading from uninitialized memory (which is readable by protected/long mode restrictions) is valid. You will get undefined values, but technically valid.

It's up to the compiler (and therefore, it's available options) what it shows to you. A higher level option might treat this as an error and stop; But technically it's possible.

Michael Chourdakis
  • 10,345
  • 3
  • 42
  • 78