V599. The virtual destructor is not present, although the 'Foo' class contains virtual functions.
Анализатор обнаружил потенциальную ошибку, связанную с отсутствием в базовом классе виртуального деструктора.
Чтобы анализатор выдал предупреждение V599 необходимо, чтобы выполнились следующие условия:
1) Объект класса уничтожается с помощью оператора delete.
2) Класс имеет хотя бы одну виртуальную функцию.
Наличие виртуальных функций говорит о том, что класс могут использовать полиморфно. В этом случае виртуальный деструктор необходим, чтобы корректно разрушить объект.
Рассмотрим пример кода.
class Father
{
public:
Father() {}
~Father() {}
virtual void Foo() { ... }
};
class Son : public Father
{
public:
int* buffer;
Son() : Father() { buffer = new int[1024]; }
~Son() { delete[] buffer; }
virtual void Foo() { ... }
};
...
Father* object = new Son();
delete object; // Call ~Father()!!
Нижеприведённый код является некорректным и приводит к утечке памяти. В момент уничтожения объекта (delete object;) вызывается только деструктор в классе 'Father'. Чтобы вызвать деструктор класса 'Son' необходимо сделать деструктор виртуальным.
Корректный код:
class Father
{
public:
Father() {}
virtual ~Father() {}
virtual void Foo() { ... }
};
Диагностическое сообщение V599 помогает выявить далеко не все проблемы связанные с отсутствием виртуальных деструкторов. Приведем соответствующий пример: "Вы разрабатываете библиотеку. В ней есть класс XXX, в котором есть виртуальные функции, но нет виртуального деструктора. Вы в библиотеке сами не работаете с этим классом, и анализатор не предупредит об опасности. Проблема может возникнуть у программиста, использующего вашу библиотеку и наследующего свои классы от класса XXX."
Намного больше проблем позволяет выявить диагностическое предупреждение C4265: 'class' : class has virtual functions, but destructor is not virtual, реализованная в Visual C++. Это очень полезная диагностика. Но по умолчанию она выключена. Почему эта диагностика отключена я ответить затрудняюсь. Обсуждение этой темы поднималось на сайте Stack Overflow: Why is C4265 Visual C++ warning (virtual member function and no virtual destructor) off by default? К сожалению толкового объяснения дать никто не смог.
Мы предполагаем, что предупреждение C4265 дает много срабатываний в коде, где используется паттерн примесь (подмешивание). При использовании этого паттерна возникает множество интерфейсных классов. Они содержат виртуальные функции, но виртуальный деструктор в них не нужен.
Можно сказать, что диагностическое правило V599 является частным случаем C4265. Оно дает меньше ложных срабатываний, но, к сожалению, позволяет выявить меньшее количество дефектов. Если вы хотите провести более тщательный анализ своего кода, то включите предупреждение C4265.
P. S.
К сожалению, ВСЕГДА объявлять деструктор виртуальным, не является идеальной практикой программирования. Это приводит к дополнительным накладным расходам, так как в классе появляется указатель на таблицу виртуальных методов.
P.P.S.
Родственным диагностическим сообщением являются V689.
Дополнительная информация:
- Wikipedia. Таблица виртуальных методов.
- Wikipedia. Виртуальный метод (виртуальная функция).
- Wikipedia. Деструктор.
- Сергей Олендаренко. Виртуальные функции и деструктор.
Выявляемые диагностикой ошибки классифицируются согласно ГОСТ Р 71207–2024 как критические и относятся к типу: Ошибки управления динамической памятью (выделения, освобождения, использования освобожденной памяти), Ошибки утечек памяти, незакрытых файловых дескрипторов и дескрипторов сетевых соединений. |
Данная диагностика классифицируется как:
|
Взгляните на примеры ошибок, обнаруженных с помощью диагностики V599. |