4

I have a small program, below, which uses an uninitialized field in a struct. I compile the program with -Wuninitialized -Wmissing-field-initializers -Wall -Wextra -Werror (Godbolt link below), and the program compiles OK and runs, but prints uninitialized garbage values when reading the struct.

Is there a way to get a warning for this kind of programming error, where an uninitialized variable is used?

#include <stdio.h>

enum FWPixelDepth {
    FWPixelDepthColor8888,
};

struct FWBitmapDecodeOptions {
    FWPixelDepth pixelDepth;
    float scale;
    bool decodeWithoutPremultiply;
};

static void p(FWBitmapDecodeOptions opts) {
    printf("%d, %f, %d", opts.pixelDepth, opts.scale, opts.decodeWithoutPremultiply);
}

int main() {
    FWBitmapDecodeOptions opts;
    opts.decodeWithoutPremultiply = true;
    p(opts);
}

https://godbolt.org/z/cjc8cY

Clang 8.0.0 flags: -O3 -Wuninitialized -Wmissing-field-initializers -Wall -Wextra -Werror

Sample output:

-1557482600, 0.000000, 1
nmr
  • 16,625
  • 10
  • 53
  • 67
  • 3
    fyi gcc does warn live - https://godbolt.org/z/bG8TPY – Richard Critten Sep 29 '20 at 23:15
  • 3
    GCC 9.1 does, but 10.2 does not appear to. – nmr Sep 29 '20 at 23:19
  • When compiling the static function, gcc has no means of determining whether the parameter's fields are not initialized. This determination requires some fairly advanced analysis at the call site, it's not surprising that not every compiler can figure this out. – Sam Varshavchik Sep 29 '20 at 23:22
  • If you toggle optimization off (using gcc 9.1) the warning(s) disappear. – Richard Critten Sep 29 '20 at 23:24
  • Right, but it is easier to detect use at the statement `p(opts)`. That is where I would like a warning, ideally. – nmr Sep 29 '20 at 23:24
  • @nmr But if the body of `p(opts)` does not read from any of the un-initialised fields then there is no issue to be diagnosed. So the compiler has to go into the call. – Richard Critten Sep 29 '20 at 23:25
  • The statement `p(opts);` copies the struct, doesn't that count as reading the uninitialized field? – nmr Sep 29 '20 at 23:26
  • 2
    ... yes, it's UB. https://stackoverflow.com/questions/60112841/copying-structs-with-uninitialized-members – user202729 Sep 29 '20 at 23:28
  • Sure, obviously it's UB, that's why I would like a diagnostic :) – nmr Sep 29 '20 at 23:32
  • 1
    re my _"... gcc does warn live..."_ above - gcc is warning too late. The UB happens when the parameter is copied, at the initial call site `p(opts);` – Richard Critten Sep 29 '20 at 23:43
  • 1
    Related: https://gcc.gnu.org/wiki/Better_Uninitialized_Warnings#line-380 . – user202729 Sep 30 '20 at 06:22

1 Answers1

3

In contrast to other programming languages, in C++, it is normally not possible to detect at run-time whether a variable with a POD type is initialized or not, when it is used. In order to detect this, every variable would need an associated flag which specifies whether the variable is initialized or not. This would cost a significant amount of space and performance. For this reason, such run-time checks are generally only done by some higher-level programming languages.

However, at compile-time, it may be possible for the compiler to detect read access to uninitialized data in simple cases, when there is a very limited number of possible code paths. But this is bound to be unreliable, as the compiler cannot be expected to always be able to check all possible code paths.

Therefore, in order to detect read access to uninitialized data, you are probably better off using a special debugging tool which detects such errors at run-time and sacrifices performance in order to do so. Examples of such tools are valgrind and the Clang memory sanitizer.

Andreas Wenzel
  • 22,760
  • 4
  • 24
  • 39
  • This isn't wrong but it's not a compiler diagnostic, which was what the question was asking for. I already know about and use ubsan et al, so this does not help me. – nmr Sep 30 '20 at 14:18
  • 1
    @nmr: I believe that my answer is a valid answer to the question, as the question asked for "a warning for this kind of programming error", without specifying whether these warnings should be compile-time or run-time. Since compile-time warnings are inherently unreliable for these types of errors, it seemed appropriate to focus on run-time warnings. I'm sorry that my answer did not help you. – Andreas Wenzel Sep 30 '20 at 14:53
  • Yeah, fair enough. I meant compiler warning FWIW. – nmr Sep 30 '20 at 15:03
  • It may help someone else, hope it does. – nmr Sep 30 '20 at 15:04