V595. Pointer was used before its check for nullptr. Check lines: N1, N2.
The analyzer has detected a potential error that may cause dereferencing of a null pointer.
The analyzer has noticed the following situation in the code: a pointer is being used first and only then it is checked whether or not this is a NULL pointer. It means one of the two things:
1) An error occurs if the pointer is equal to NULL.
2) The program works correctly, since the pointer is never equal to NULL. The check is not necessary in this case.
Let's consider the first case. There is an error.
buf = Foo();
pos = buf->pos;
if (!buf) return -1;
If the 'buf' pointer is equal to NULL, the 'buf->pos ' expression will cause an error. The analyzer will generate a warning for this code mentioning 2 lines: the first line is the place where the pointer is used; the second line is the place where the pointer is compared to NULL.
This is the correct code:
buf = Foo();
if (!buf) return -1;
pos = buf->pos;
Let's consider the second case. There is no error.
void F(MyClass *p)
{
if (!IsOkPtr(p))
return;
printf("%s", p->Foo());
if (p) p->Clear();
}
This code is always correct. The pointer is never equal to NULL. But the analyzer does not understand this situation and generates a warning. To make it disappear, you should remove the check "if (p)". It has no sense and can only confuse a programmer reading this code.
This is the correct code:
void F(MyClass *p)
{
if (!IsOkPtr(p))
return;
printf("%s", p->Foo());
p->Clear();
}
When the analyzer is mistaken, you may use (apart from changing the code) a comment to suppress warnings. For example: "p->Foo(); //-V595".
Note N1.
Some users report that the analyzer generates the V595 warning on correct code like in the following sample:
static int Foo(int *dst, int *src)
{
*dst = *src; // V595 !
if (src == 0)
return 0;
return Foo(dst, src);
}
...
int a = 1, b = 2;
int c = Foo(&a, &b);
Yes, analyzer produces a false-positive warning here. The code is correct and the 'src' pointer cannot be equal to NULL at the moment when assignment "*dst = *src" is performed. Perhaps we will implement an exception for such cases in future but we won't hurry. Though there is no error, the analyzer has detected a surplus code: the function can be shortened and the V595 warning will stop appearing, while the code will become simpler.
This is the better code:
int Foo(int *dst, int *src)
{
assert(dst && src);
*dst = *src;
return Foo(dst, src);
}
Note N2.
Sometimes programmers write code like this:
int *x=&p->m_x; //V595
if (p==NULL) return(OV_EINVAL);
In this fragment, a pointer to a class member is calculated. This pointer is not dereferenced and one may find it strange that the analyzer generates the V595 warning here. But this code actually leads to undefined behavior. It's only sheer luck that the program works properly. One can't calculate the "&p->m_x" expression if the 'p' pointer is null.
A similar issue may occur when sorting an array:
int array[10];
std::sort(&array[0], &array[10]); // Undefined behavior
&array[10] will cause undefined behavior as the array[10] item lies outside the array boundaries. However, it is legal to use pointer arithmetic: you can use a pointer addressing the last array item. So the fixed code may look like this:
int array[10];
std::sort(array, array+10); //ok
Related materials
- Andrey Karpov. Explanation on Diagnostic V595. http://www.viva64.com/en/b/0353/
This diagnostic is classified as:
|
You can look at examples of errors detected by the V595 diagnostic. |