警告 C26430
未在所有路徑上測試符號是否為 Null。
C++ Core Guidelines:F.23:使用 not_null<T> 表示“null” 不是有效值
如果程式碼曾經檢查指標變數是否為 Null 值,則應該一致地執行,並驗證所有路徑上的指標。 有時候,寧可過度執行 Null 檢查,也不要有其中一個複雜分支發生封鎖性損毀的可能性。 在理想情況下,應重構這類程式碼使其較不複雜 (透過將其分割成多個函式),並依賴 gsl::not_null
之類的標記。 這些標記可讓程式碼隔離演算法的各部分,以安全地假設指標值有效。 TEST_ON_ALL_PATHS
規則有助於尋找 Null 檢查不一致的地方 (這表示可能需要檢閱假設)。 或者,它會尋找潛在 Null 值可能在某些程式碼路徑中略過 Null 檢查的實際 Bug。
備註
此規則預期程式碼會對指標變數進行取值 (Dereference),以正當化 Null 檢查 (或強制執行非 Null 值)。 如果沒有取值,則會暫停規則。
目前的實作只會處理簡單的指標 (或其別名),不會偵測智慧指標,但 Null 檢查也適用於智慧指標。
當變數用於下列內容時,會標示為檢查是否為 Null:
- 作為分支條件中的符號運算式,例如在
if (p) { ... }
中; - 在非位元邏輯運算中;
- 在比較運算中,其中一個運算元是評估為零的常數運算式。
透過下列方式指派指標值時,會假設隱含 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);
}
}
啟發學習法
確保指標的取值不是 Null 時,此規則不需要「每個」取值都要事先進行 Null 檢查。 相反地,它需要在指標的「第一個」取值之前進行 Null 檢查。 下列函式不會觸發 C26430:
void f(int* p)
{
if (p)
*p = 1;
*p = 2;
}
下列函式會產生 C26430,因為有一個指派 *p
的路徑未進行 Null 檢查:
void f(bool b, int* p)
{
if (b && p)
*p = 1;
*p = 2;
}
C26822 和 C26823 規則適用於取值的指標 (可能) 為 Null 的情況。
此規則不會執行完整的資料流程追蹤。 在使用間接檢查的情況下 (例如當中繼變數包含 Null 值並在稍後用於比較時),可能會產生不正確的結果。