Warning C26441

Guard objects must be named (cp.44)

C++ Core Guidelines: CP.44: Remember to name your lock_guards and unique_locks

The standard library provides a few useful classes that help to control concurrent access to resources. Objects of such types lock exclusive access during their lifetime. Lifetime management implies that every lock object must be named. That is, it must have a clearly defined lifetime that spans through the period in which access operations are executed. So, failing to assign a lock object to a variable is a mistake that effectively disables the locking mechanism (because temporary variables are transient). This rule tries to catch simple cases of such unintended behavior.

Remarks

  • Only standard lock types are tracked: std::scoped_lock, std::unique_lock, and std::lock_quard.

  • Only simple calls to constructors are analyzed. More complex initializer expressions may lead to inaccurate results, but it's an unusual scenario.

  • Locks passed as arguments to function calls or returned as results of function calls are ignored.

  • Locks created as temporaries but assigned to named references to extend their lifetime are ignored.

Code analysis name: NO_UNNAMED_GUARDS

Example

Missing scoped variable:

void print_diagnostic(gsl::string_span<> text)
{
    auto stream = get_diagnostic_stream();
    if (stream)
    {
        std::lock_guard<std::mutex>{ diagnostic_mutex_ }; // C26441
        write_line(stream, text);
        // ...
    }
}

Missing scoped variable, corrected:

void print_diagnostic(gsl::string_span<> text)
{
    auto stream = get_diagnostic_stream();
    if (stream)
    {
        std::lock_guard<std::mutex> lock{ diagnostic_mutex_ };
        write_line(stream, text);
        // ...
    }
}