경고 C26430
모든 경로에서 기호의 nullness가 테스트되지는 않습니다.
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) { ... }
) - 비트 이외 논리 연산에서
- 하나의 피연산자가 0으로 계산되는 상수 식인 비교 연산에서
다음에서 포인터 값이 할당될 때 암시적 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;
}
다음 함수는 null 검사 없이 *p
를 할당하는 경로가 있으므로 C26430을 생성합니다.
void f(bool b, int* p)
{
if (b && p)
*p = 1;
*p = 2;
}
C26822 및 C26823 규칙은 (아마도) null 포인터 역참조에 적용됩니다.
이 규칙은 전체 데이터 흐름 추적을 수행하지는 않습니다. 중간 변수가 null 값을 보유하고 나중에 비교에 사용되는 경우와 같이 간접 검사가 사용되는 경우 잘못된 결과를 생성할 수 있습니다.