Uninitialized class member
| Vulnerability potential | Medium |
| DDoS potential | Low |
One or more class members might be uninitialized
Impact
A constructor that does not initialize every data member leaves those members holding indeterminate values for objects with automatic or dynamic storage. Methods that later read such a member operate on garbage: a flag is randomly true or false, a count is enormous, a pointer member points nowhere in particular. Because the object otherwise looks fully constructed, the bug surfaces only when that member is used, often far from the constructor, and may behave differently between debug and release builds or between consecutive allocations.
Vulnerability potential
This issue has a meaningful potential to be a vulnerability.
- An uninitialized pointer or handle member that is later dereferenced or freed leads to wild reads/writes, use-after-free-like corruption, or double frees — classic paths to memory corruption and code execution.
- An uninitialized size or length member used to bound a copy or loop can drive a buffer overflow or massive over-read.
- If the object (or a sub-object) is serialized, copied into an output buffer, or sent across a trust boundary, the indeterminate member leaks whatever heap or stack residue occupied that memory, disclosing pointers or secrets.
Technical details
In C++ a member of class type is default-constructed if not mentioned in the
initializer list, but members of built-in type (int, bool, raw pointers,
enum) and arrays of them are left uninitialized unless the constructor lists
them, a default member initializer is provided, or the object is value-/aggregate-
initialized with {}. Reading such a member before assignment is undefined
behavior.
Initializer list vs assignment in body
Initialize members in the constructor’s member initializer list, not by
assignment in the body; members are initialized in declaration order regardless
of list order, and a body assignment runs after default initialization. A
-Wreorder warning hints when the list order diverges from declaration order.
Easy ways to get it wrong
Adding a new member but forgetting to update every constructor; multiple
constructors where only some initialize a member; and = default constructors
for classes with built-in members (which do not zero them for non-aggregate
automatic objects).
Prefer default member initializers
Since C++11, int count_ = 0; / T *p_ = nullptr; at the point of declaration
guarantees a sane value in every constructor and is the most robust fix.
Catching the issue
Compiler warnings
GCC/Clang: -Wuninitialized, -Wmaybe-uninitialized, and (Clang)
-Wuninitialized-const-reference; also -Weffc++ flags members missing from the
initializer list. MSVC /W4 and /sdl report uninitialized members. Build with
-Werror.
Sanitizers and analysis
MemorySanitizer (-fsanitize=memory) and Valgrind Memcheck catch the read of an
uninitialized member at runtime. clang-tidy
(cppcoreguidelines-pro-type-member-init) flags constructors that fail to
initialize all members; Coverity and PVS-Studio (V730) do the same statically.
As a rule, give every member a default member initializer.
How to reproduce
Run under clang -fsanitize=memory; reading ready_ reports a use of
uninitialized value, and the printed result is unpredictable.
#include <iostream>
struct Widget {
int id_;
bool ready_; // never initialized
Widget() : id_(1) {} // forgot ready_
bool usable() const { return ready_ && id_ > 0; }
};
int main() {
Widget w;
std::cout << w.usable() << "\n"; // depends on garbage in ready_
}