警告 C26429
シンボルは null 値のテストを行うことはなく、
gsl::not_null
としてマークできます。
C++ コア ガイドライン: F.23: not_null<T>
を使用して、"null" が有効な値ではないことを示します
アサートを使用して、ポインター値の有効性に関する前提条件を適用するのが一般的な方法です。 問題は、アサートがインターフェイス (戻り値の型やパラメーターなど) を介して仮定を公開してはいけないという問題です。 アサートは維持が難しく、他のコード変更と常に同期することも困難です。 ガイドライン サポート ライブラリの gsl::not_null
を使用して、null 値を設定してはいけないリソースをマークすることをお勧めします。 ルール USE_NOTNULL
は、null チェックを省略する場所を特定するのに役立ちます。そのため、 gsl::not_null
を使用するように更新できます。
解説
ルールのロジックでは、null チェック (または null 以外の値の適用) が正当化されるように、ポインター変数を逆参照するコードが必要です。 そのため、警告は、ポインターが逆参照され、null のテストが行われなかった場合にのみ生成されます。
現在の実装では、単純なポインター (またはそのエイリアス) のみを処理し、スマート ポインターにも gsl::not_null
を適用できますが、スマート ポインターを検出しません。
変数が以下のコンテキストで使用される場合、その変数は null チェック済みとマークされます。
- たとえば、
if (p) { ... }
など、分岐条件のシンボル式として。 - ビットごとではない論理演算
- 1 つのオペランドが 0 に評価される定数式である比較演算
ルールには完全なデータフロー追跡がありません。 間接チェックが使用される場合 (中間変数が null 値を保持し、後で比較で使用される場合など) に、不適切な結果が生じる可能性があります。
コード分析名: USE_NOTNULL
例
隠された期待:
using client_collection = gsl::span<client*>;
// ...
void keep_alive(const connection *connection) // C26429
{
const client_collection clients = connection->get_clients();
for (ptrdiff_t i = 0; i < clients.size(); i++)
{
auto client = clients[i]; // C26429
client->send_heartbeat();
// ...
}
}
gsl::not_null
によって明確にされた隠れた期待:
using client_collection = gsl::span<gsl::not_null<client*>>;
// ...
void keep_alive(gsl::not_null<const connection*> connection)
{
const client_collection clients = connection->get_clients();
for (ptrdiff_t i = 0; i < clients.size(); i++)
{
auto client = clients[i];
client->send_heartbeat();
// ...
}
}