56

I am looking for an easy way to find uninitialized class member variables.

Finding them in either runtime or compile time is OK.

Currently I have a breakpoint in the class constructor and examine the member variables one by one.

2
  • Good article "In search of uninitialized class members" - viva64.com/en/b/0354 Commented Oct 29, 2015 at 14:38
  • In case of using clang compiler you can try memory sanitizer: clang.llvm.org/docs/MemorySanitizer.html. It perform dynamic checking and has significantly less overhead compared to valgrind. There is nice presentation from the author on cppcon2014 youtube.com/watch?v=V2_80g0eOMc Commented Feb 2, 2016 at 15:24

11 Answers 11

33

If you use GCC you can use the -Weffc++ flag, which generates a warnings when a variable isn't initialized in the member initialisation list. This:

class Foo { int v; Foo() {} }; 

Leads to:

$ g++ -c -Weffc++ foo.cpp -o foo.o foo.cpp: In constructor ‘Foo::Foo()’: foo.cpp:4: warning: ‘Foo::v’ should be initialized in the member initialization list 

One downside is that -Weffc++ will also warn you when a variable has a proper default constructor and initialisation thus wouldn't be necessary. It will also warn you when you initialize a variable in the constructor, but not in the member initialisation list. And it warns on many other C++ style issues, such as missing copy-constructors, so you might need to clean up your code a bit when you want to use -Weffc++ on a regular basis.

There is also a bug that causes it to always give you a warning when using anonymous unions, which you currently can't work around other then switching off the warning, which can be done with:

#pragma GCC diagnostic ignored "-Weffc++" 

Overall however I have found -Weffc++ to be incredible useful in catching lots of common C++ mistakes.

Sign up to request clarification or add additional context in comments.

2 Comments

is the bug still there?
my Compiler (g++ 4.3.3) is able to detect only a part of non initialized members. It can't detect non initialize simple type arrays: no warning is produced and int array is not initiazed at execution
13

cppcheck will find this, e.g.:

cppcheck my_src_dir --output-file=check.txt --inconclusive --enable=warning 

3 Comments

Probably because cppcheck is not that smart. It will warn against not initializing in the constructor, but it most often cannot examine complicated paths where e.g setters in constructors initialize a member.
Cppcheck has been improved since then, version 1.75 is able to detect only partial struct initializations. But of course some cases like this one are still too hard for it, though also hard for humans (as I observed).
It still doesn't understand delegating constructors.
12

Valgrind (FREE, on Linux) and Purify (on Windows) find un-initialized variables, invalid pointers and such by running your code in a special virtual machine.

This is easy to use and extremely powerful; it will likely find many bugs beyond the obvious un-initialized variables.

Coverity, Klocwork and Lint can find un-initialized variables using static code analysis.

3 Comments

"Easy to use" is subjective. With a GCC extended assembly block, all we get is a line number pointing to the end of the block (the closing paren), and not the actual variable causing the problem. That's even with --track-origins.
@jww this is a gcc problem (not producing enough debug info), not a valgrind problem. It might go away if you compile your source with -ggdb or something, but I'd be surprised. I'm working in llvm backends and its much the same situation there.
It seems that purify is no longer a a good option: marlowa.blogspot.com.br/2015/08/the-death-of-purify.html
10

Valgrind can tell you if you are on linux.

1 Comment

uname -a will also tell me if I'm on Linux.... but it won't help with this ;-)
8

-Wuninitialized ?

(This only checks if a variable is used uninitialized, i.e. if

struct Q { int x, y; Q() : x(2) {} int get_xy() const { return x*y; } }; 

g++ will warn only when the user calls get_xy() without assigning to y.)

3 Comments

Also requires -O1 or above, which isn't the default.
I am unable to get g++ 4.3.3 to warn for data members with -Wuninitialized, are you sure it works here? (Simple test: add int main() { return Q().get_xy(); } to your code.)
@Roger-plate: Unfortunately you need to use int main() { Q q; return q.get_xy(); } to work.
5

If you're using Visual Studio, you could compile in debug mode, stop the program in the debugger and look for which variables are initialised to bytes containing 0xCC (stack) or 0xCD (heap).

Though personally, I'd invest in a static analysis tool for a more thorough approach.

Comments

5

Visual Studio (MSVC) has a /sdl (Enable Additional Security Checks) compiler option (http://msdn.microsoft.com/en-us/library/jj161081.aspx). At run-time, it:

Performs class member initialization. Automatically initializes class members of pointer type to zero on object instantiation (before the constructor runs). This helps to prevent use of uninitialized data associated with class members that the constructor does not explicitly initialize.

This will not help you detect uninitialized member variables at compile-time, but it makes the behaviour more predictable when it happens at run-time. You shouldn't write code that relies on this option being enabled though, of course.

Comments

2

/analyze on Visual Studio ("Team System")

1 Comment

Are you sure this works for uninitialized member variables? In our tests, it only finds uninitialized local variables.
0

Beware! Compiler options proposed here are neither reliable, nor version-independent. Consider the simple example:

class A { int a; public: void mA() { printf("haha"); ++a; int g = 2/a; printf("%i\n",g); } }; int main() { A a; a.mA(); } 

Compiled with g++ -O3 -Weffc++ -Wuninitialized this thing reports uninitialized on gcc versions up to 4.6 inclusive, and passess happily on 4.7 and 4.8 (tested on MacPorts). Then, curiously, if we remove the printf("haha");, both 4.7 and 4.8 suddenly see uninitialized A::a. Clang is a little better, since it somehow assigns rubbish (instead of convenient 0) to uninitialized vars, so you see their disastrous effect easier/sooner.

I didn't have much luck in spotting the above uninitialized A::a with valgrind either; maybe the gentlement suggesting valgrind could provide appropriate options to spot this error.

Bottom line: great question, not much reliable solutions at the moment... (the way I see it).

1 Comment

With any optimization level above -O0, gcc 4.7 optimizes out everything except the calls to printf. I checked the assembly code and it's just two calls to printf. So gcc's compile-time evaluation is not detecting the uninitialized value. And valgrind has no chance to detect it at runtime since it's only two calls to printf with constant arguments.
0

Clang with clang-analyze is able to do this. It will event create a nice HTML report that indicates when the unused variable is accessed.

Comments

-2

Consider the following code

unint.cpp:

int main() { int a; int b; a++; b = b + 5; return 0; } 

If the code is compiled with following comment, the warning messages shall be displayed.

g++ -O3 -Wuninitialized unint.cpp

Note: the -Wuninitialized needs the -O3 option also.

2 Comments

The output:unint.cpp: In function 'int main()': unint.cpp:8: warning: 'a' is used uninitialized in this function unint.cpp:9: warning: 'b' is used uninitialized in this function
The question is titled "Easy way [to] find uninitialized member variables". These are not member variables. We all know about -Wunitialized for non-member variables, and we should all have it already as part of already using -Wall -Wextra -Wpedantic. Also, it does not "need the -O3 option" or any other form of optimisation to be present or absent, although they may affect which warnings are returned if optimisation causes side-effect-less variables to be removed.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.