V717. It is suspicious to cast object of base class V to derived class U.
Анализатор заметил в коде ситуацию необычного приведения типов: указатель на объект базового класса жёстко приводится к указателю на производный класс. Причём известно, что указатель на базовый класс действительно указывает на объект базового класса.
Приведение указателей производного класса к базовому – вполне типичная ситуация. А вот приведение базового класса к одному из производных, может иногда быть ошибочным. Если приведение типов выполнено неправильно, то попытка обращения к членам производного класса может привести к Access Violation или ко всему чему угодно.
Иногда программисты допускают ошибки, приводя к производному классу указатель именно на базовый класс. Пример из реального приложения:
typedef struct avatarCacheEntry { .... };
struct CacheNode : public avatarCacheEntry,
public MZeroedObject
{
....
BOOL loaded;
DWORD dwFlags;
int pa_format;
....
};
avatarCacheEntry tmp;
....
CacheNode *cc = arCache.find((CacheNode*)&tmp);
// Далее при попытке обращения, например, к
// cc->loaded, произойдёт ошибка времени выполнения.
К сожалению, в данном случае сложно привести какие-то конкретные рекомендации по устранению некорректной ситуации – скорее всего, потребуется заняться рефакторингом кода с целью его улучшения и увеличения удобочитаемости, а также для предотвращения потенциальных ошибок в будущем. Например, если обращение к новым полям не требуется, то тогда можно подменить указатель на базовый класс на указатель на производный.
Следующий код анализатором считается корректным:
base * foo() { .... }
derived *y = (derived *)foo();
Здесь дело в том, что функция foo() может на самом деле всегда возвращать указатель на один из производных классов, и приведение её результата к производному классу – вполне обыденное явление. Вообще, анализатор выдаёт предупреждение V717 только в том случае, если точно известно, что именно базовый класс приводится к производному. Однако, анализатор не будет выдавать предупреждение V717 в том случае, если в производном классе нет новых нестатических членов (хотя всё равно так делать нехорошо, но это уже ближе к нарушению хорошего стиля кода, нежели к настоящей ошибке):
struct derived : public base
{
static int b;
void bar();
};
....
base x;
derived *y = (derived *)(&x);
Данная диагностика классифицируется как: