Static variable must be initialized

Vulnerability potential Low
DDoS potential None

Missing initializer of a static variable is suspicious

Impact

A static or global variable without an explicit initializer is zero-initialized by the language, so the immediate effect is not corruption but ambiguity: a reader cannot tell whether zero is the intended starting value or whether an initializer was forgotten. When the intended initial value is not zero — a sentinel like -1, a non-null default pointer, a configuration default — the missing initializer is a latent logic bug. The variable will read as 0/NULL, which may silently mean “uninitialized”, “first call”, or an invalid state the rest of the code does not expect.

Vulnerability potential

Direct security relevance is low, because the value is well-defined (zero) rather than indeterminate. The realistic risk is logical: a security-relevant static flag intended to default to a safe non-zero value (for example a min_tls_version or an initialized guard) that instead defaults to zero can leave a feature disabled or a check skipped. Such a misconfiguration could weaken a protection, but the language guarantee of zero-initialization rules out the indeterminate-value class of memory-safety bugs.

Technical details

In C and C++ objects with static storage duration (file-scope variables and function-local statics) are guaranteed to be zero-initialized before any dynamic initialization runs — pointers become null, arithmetic types become zero, aggregates are zeroed member-wise. This is fundamentally different from automatic (stack) variables, which are left indeterminate.

Why it is still flagged

The defect is a style and intent signal, not undefined behavior. Many coding standards (MISRA, and various house styles) require every object to have an explicit initializer so that the intended value is visible and a forgotten initializer is not silently absorbed into the zero default.

C++ subtleties

For non-trivial types, default-initialization of a namespace-scope object runs the default constructor during dynamic initialization, and the static initialization order fiasco can make one translation unit observe another’s static before its constructor has run. An explicit, constant initializer (constinit, constant expressions) avoids both the ambiguity and the ordering hazard.

Catching the issue

Compiler and standards checkers

MISRA/AUTOSAR checkers (Coverity, PVS-Studio, Cppcheck with the MISRA add-on, Parasoft) report missing explicit initializers where the active standard requires them. clang-tidy’s cppcoreguidelines-* checks encourage explicit initialization.

C++ ordering hazards

For cross-TU initialization order, use Clang’s -Wglobal-constructors to find dynamic initializers, prefer constinit/constexpr for compile-time constants, and use the function-local-static (“Meyers singleton”) idiom when lazy, ordered initialization is needed.

How to reproduce

The intended sentinel is -1, but without an initializer the static reads as 0, so the “not yet computed” guard never triggers.

#include <stdio.h>

static int cached_result;   /* meant to start at -1, but is zero-initialized */

int compute(void) {
    if (cached_result == -1)        /* never true: it is 0, not -1 */
        cached_result = 42;          /* expensive computation, here skipped */
    return cached_result;
}

int main(void) {
    printf("%d\n", compute());      /* prints 0, not 42 */
    return 0;
}