This code is missing a constructor initializer list:
#include <cstdio>
struct s {
s() {} // should be s(): m() {}
int m;
};
int main() {
struct s *px = new s();
if (px->m) {
printf("true\n");
} else {
printf("false\n");
}
delete px;
return 0;
}
gcc compiles cleaning with no warnings:
$ g -Wall -Wextra -g -O2 test.cpp
However, valgrind knows that the class member m
wasn't initialized:
$ valgrind ./a.out
==10953== Conditional jump or move depends on uninitialised value(s)
==10953== at 0x400512: main (test.cpp:10)
==10953==
Why didn't gcc warn about the missing initialization (-Wmissing-field-initializers
or -Wuninitialized
or -Wmaybe-uninitialized
)?
Is there a flag I can pass that will catch this case?
CodePudding user response:
You could add -Weffc
to catch it (inspired by Scott Meyers book "Effective C "). Strangely enough it does not refer to any other -W
option (and neither does clang
).
The option is however considered, by some, a bit outdated by now, but in this case, it's finding a real problem.
CodePudding user response:
GCC also has the -fanalyzer
flag which does some deeper static analysis than the warning flags do and can catch this specific case on current trunk (but not in GCC 11.2 or earlier):
<source>:10:13: warning: use of uninitialized value '*px.s::m' [CWE-457] [-Wanalyzer-use-of-uninitialized-value]
10 | if (px->m) {
| ~~~~^
'int main()': events 1-2
|
| 9 | struct s *px = new s();
| | ^
| | |
| | (1) region created on heap here
| 10 | if (px->m) {
| | ~~~~~
| | |
| | (2) use of uninitialized value '*px.s::m' here
|
But I often seem to have problems with the flag for generating false positives. For example in this case it complains about operator new
potentially returning a null pointer, which cannot ever happen (bug).
See docs for details.