There is a common C++ bug with uninitialised primitive members:
#include <iostream>
class A {
public:
int x;
};
int main() {
A a;
std::cout << a.x;
return 0;
}
a.x
will be uninitialised. I understand why it happens and want to find a solution for catching such bugs. I checked gcc and cppcheck, they don't report these members.
EDIT
Checked gcc with flags -Wall -Wextra -Werror -pedantic -Wold-style-cast -Wconversion -Wsign-conversion -Wunreachable-code
The first version of gcc that detects a bug is 5.1. g++-4.9 doesn't detect it, clang++-3.6 fails too.
Yes they do… sort of:
main.cpp: In function 'int main()':
main.cpp:10:18: warning: 'a.A::x' is used uninitialized in this function [-Wuninitialized]
std::cout << a.x;
^
0
In the above linked example, I'm using GCC 5.1 trunk with -Wall
.
Turn on more GCC warnings and/or upgrade.
Also tested, and found not to warn:
Honestly I'm not sure what else you can do. You could create a tool to do this, but then you'd be creating a compiler or static analyser. :)
So, I guess, just hope the people who know how to do that catch up…
This bug is diagnosed by valgrind
with the (default) tool memcheck
, producing a number of warnings, including:
$ valgrind ./unin
…
==12185== Use of uninitialised value of size 8
==12185== at 0x4F39BC3: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)
==12185== by 0x4F3AD89: std::ostreambuf_iterator<char, std::char_traits<char> > std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::_M_insert_int<long>(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, long) const (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)
==12185== by 0x4F3AF8C: std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::do_put(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, long) const (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)
==12185== by 0x4F474E9: std::ostream& std::ostream::_M_insert<long>(long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)
==12185== by 0x400763: main (in [censored]/unin)
It should also be found by Clang's address sanitizer. However, I realize you are most interested in a compile-time check. After all, the existing test suites may never execute some of the code, and catching a bug sooner is always better. You could use GCC 5.1 (even if you used it only for this purpose), or you could use a dedicated static analyzer. Fortunately, clang comes with a static analyzer invoked as scan-build
(included in at least the Debian/Ubuntu packages):
$ scan-build clang -c unin.cxx
scan-build: Using '/usr/lib/llvm-3.6/bin/clang' for static analysis
unin.cxx:10:3: warning: Function call argument is an uninitialized value
std::cout << a.x;
^~~~~~~~~~~~~~~~
1 warning generated.
scan-build: 1 bug found.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With