>
>
>
V599. The virtual destructor is not pre…


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.

Дополнительная информация:

Выявляемые диагностикой ошибки классифицируются согласно ГОСТ Р 71207–2024 как критические и относятся к типу: Ошибки управления динамической памятью (выделения, освобождения, использования освобожденной памяти), Ошибки утечек памяти, незакрытых файловых дескрипторов и дескрипторов сетевых соединений.

Данная диагностика классифицируется как:

Взгляните на примеры ошибок, обнаруженных с помощью диагностики V599.