警告 C26441
ガード オブジェクトには名前を付ける必要があります (cp.44)
C++ Core Guidelines
CP.44: lock_guard
と unique_lock
に名前を付ける
解説
標準ライブラリは、リソースの有効期間中にリソースへの同時アクセスを制御するのに役立つロックを提供します。 名前を指定せずにロック オブジェクトを宣言すると、コンパイラは、外側のスコープの末尾に存在するのではなく、直ちに破棄される一時オブジェクトを作成します。 したがって、ロック オブジェクトを変数に割り当てなくなると、(一時変数は一時的な変数であるため) ロック メカニズムが効果的に無効になります。 このルールは、このような意図しない動作の単純なケースをキャッチします。
この診断では、 std::scoped_lock
、 std::unique_lock
、および std::lock_guard
の標準ロックの種類のみが分析されます。 警告 C26444 には、他の名前のない RAII 型が含まれます。
アナライザーは、コンストラクターの単純な呼び出しのみを分析します。 より複雑な初期化子式は、誤った警告の形式で不正確な結果を招く可能性があります。 アナライザーは、関数呼び出しに引数として渡されるか、関数呼び出しから返されたロックを無視します。 これらのロックがその関数呼び出しを意図的に保護しようとしているのか、 lifetime を拡張する必要があるかどうかを判断できません。 関数呼び出しによって返される型に対して同様の保護を提供するには、 [[nodiscard]]
で注釈を付けます。 [[nodiscard]]
を使用してコンストラクターに注釈を付けて、その型の名前のないオブジェクトを回避することもできます。
struct X { [[nodiscard]] X(); };
void f() {
X{}; // warning C4834
}
アナライザーは、一時的として作成されたが、名前付き参照に割り当てられたロックを無視して有効期間を延長します。
コード分析名: NO_UNNAMED_GUARDS
例
この例では、スコープ付きロックの名前がありません。
void print_diagnostic(std::string_view text)
{
auto stream = get_diagnostic_stream();
if (stream)
{
std::lock_guard<std::mutex>{ diagnostic_mutex_ }; // C26441
write_line(stream, text);
}
}
エラーを修正するには、ロックに名前を付けて、有効期間を延長します。
void print_diagnostic(std::string_view text)
{
auto stream = get_diagnostic_stream();
if (stream)
{
std::lock_guard<std::mutex> lock{ diagnostic_mutex_ };
write_line(stream, text);
}
}