V206. Explicit conversion from 'void *' to 'int *'.
Предупреждение информирует о наличии явного приведения типа void *
, byte *
к указателю на функцию или к указателю на 32/64-битные целочисленные типы данных, или наоборот. Cамо по себе такое приведение типа не является ошибкой.
Достаточно часто указатель на какой-то буфер памяти передаётся в другую часть программы с помощью указателя на байт или void. Причины написать такой код могут быть различны. Часто это свидетельствует о плохом дизайне. Указатели на функцию тоже часто хранятся как void *
.
В каком-то фрагменте программы указатель на массив/функцию сохраняется как void *
, а в другом происходит обратное приведение типа. При портировании в таком коде появляются ошибки. В одном месте тип данных может быть изменён, а в другом — нет.
Рассмотрим пример:
size_t array[20];
void *v = array;
....
unsigned* sizes = (unsigned*)(v);
Этот код корректно работает в 32-битном режиме, так как размеры типов unsigned
и size_t
совпадают. В 64-битном режиме размер типов отличается, и поведение программы также будет отличаться от ожидаемого. См. также: паттерн 6 — изменение типа массива.
Анализатор указывает на строку с явным приведением типа, которая содержит ошибку. Исправленный вариант кода может выглядеть так:
unsigned array[20];
void *v = array;
....
unsigned* sizes = (unsigned*)(v);
Или так:
size_t array[20];
void *v = array;
....
size_t* sizes = (size_t*)(v);
Аналогичную ошибку можно допустить при работе с указателями на функцию.
void Do(void *ptr, unsigned a)
{
typedef void (*PtrFoo)(DWORD);
PtrFoo f = (PtrFoo)(ptr);
f(a);
}
void Foo(DWORD_PTR a) { /*... */ }
void Call()
{
Do(Foo, 1);
}
Исправленный вариант кода:
typedef void (*PtrFoo)(DWORD_PTR);
Примечание. Анализатор распознает множество случаев, когда явное приведение типа безопасно. Например, он не обращает внимание на явное приведение указателя типа void *
, который вернула функция malloc()
:
int *p = (int *)malloc(sizeof(int) * N);
Как было отмечено в начале, явное приведение типа само по себе не является ошибкой. Поэтому несмотря на большое количество исключений из правила, анализатор всё равно генерирует много ложных предупреждений V206. Анализатор не знает, есть ли в программе другие места, где неправильно используются эти указатели, поэтому он выдаёт предупреждения на все потенциально опасные приведения типов.
Например, выше были приведены два примера некорректного кода и способы их исправления. Анализатор будет продолжать выдавать предупреждения на уже исправленный код.
Существует следующий способ работы с предупреждением: один раз внимательно просмотреть все сообщения V206, после чего отключить эту диагностику в настройках. Если ложных срабатываний немного, то можно воспользоваться один из методов подавления ложных предупреждений.