次の方法で共有


警告 C26430

シンボルは、すべてのパスで null 値がテストされるわけではありません。

C++ コア ガイドライン: F.23: not_null<T> を使用して、"null" が有効な値ではないことを示す

コードが null のポインター変数をチェック場合は、一貫して行い、すべてのパスでポインターを検証する必要があります。 場合によっては、複雑な分岐のいずれかでハードクラッシュが発生する可能性よりも、null に対する過剰なチェックがまだ優れている場合があります。 理想的には、このようなコードは(複数の関数に分割することによって)複雑ではなく、マーカー gsl::not_nullに依存するようにリファクタリングする必要があります。 これらのマーカーを使用すると、コードは、有効なポインター値に関する安全な想定を行うことができるアルゴリズムの一部を分離できます。 このルールTEST_ON_ALL_PATHSは、null チェックが一貫性のない場所を見つけるのに役立ちます (つまり、前提条件にレビューが必要になる場合があります)。 または、潜在的な null 値が一部のコード パスで null チェックをバイパスする可能性がある実際のバグを検出します。

解説

この規則では、コードがポインター変数を逆参照して、null チェック (または null 以外の値の適用) が正当化されることを想定しています。 逆参照がない場合、ルールは中断されます。

現在の実装では、プレーン ポインター (またはそのエイリアス) のみが処理され、スマート ポインターは検出されません。ただし、null チェックはスマート ポインターにも適用できます。

変数は、次のコンテキストで使用される場合、null に対してチェックとしてマークされます。

  • たとえば、 if (p) { ... }分岐条件のシンボル式として;
  • ビットごとの論理演算以外の場合。
  • 比較演算では、1 つのオペランドが 0 に評価される定数式です。

ルールには完全なデータ フロー追跡がありません。 間接チェックが使用される場合 (中間変数が null 値を保持し、後で比較で使用される場合など) に、不適切な結果が生じる可能性があります。

ポインター値が次の値から割り当てられると、暗黙的な null チェックが想定されます。

  • スロー operator newで実行される割り当て。
  • でマークされた型から取得された gsl::not_nullポインター。

不整合テストにより論理エラーが明らかになる

void merge_states(const state *left, const state *right) // C26430
{
    if (*left && *right)
        converge(left, right);
    else
    {
        // ...
        if (!left && !right)                            // Logic error!
            discard(left, right);
    }
}

不整合テストにより論理エラーが明らかになる - 修正後

void merge_states(gsl::not_null<const state *> left, gsl::not_null<const state *> right)
{
    if (*left && *right)
        converge(left, right);
    else
    {
        // ...
        if (*left && *right)
            discard(left, right);
    }
}