Подавить warning в древнем GCC
От: wander  
Дата: 20.01.24 10:13
Оценка:
Всем здравия.

Значит так, имеем:
1) GCC 4.1.3
2) Код, в котором куча классов с виртуальными функциями, но без виртуальных деструкторов (это чистые интерфейсы)
3) GCC выдает "warning: 'class T' has virtual functions but non-virtual destructor" при включении -Wall

Особенности:
1) Просто добавить виртуальные деструкторы — нельзя. Это by design. Нигде в том коде невозможно удалить объект такого класса через delete на базовый указатель.
2) В этом GCC нет специального ключа, отключающего этот warning (или он называется как-то нестандартно)
3) -Wall хотелось бы сохранить.

Есть ли еще какой-то способ подавить этот warning?
Спасибо.
Re: Подавить warning в древнем GCC
От: reversecode google
Дата: 20.01.24 10:19
Оценка: 4 (1)
https://stackoverflow.com/questions/10024796/c-virtual-functions-but-no-virtual-destructors

ну или strings -a g++ | grep virtual
и всматривайтесь что там есть
Re[2]: Подавить warning в древнем GCC
От: wander  
Дата: 20.01.24 13:30
Оценка:
Здравствуйте, reversecode

-Wno-non-virtual-dtor
решил вопрос.
Спасибо.
Re: Подавить warning в древнем GCC
От: fk0 Россия https://fk0.name
Дата: 20.01.24 17:49
Оценка:
Здравствуйте, wander, Вы писали:

W>Значит так, имеем:

W>1) GCC 4.1.3
W>2) Код, в котором куча классов с виртуальными функциями, но без виртуальных деструкторов (это чистые интерфейсы)
W>3) GCC выдает "warning: 'class T' has virtual functions but non-virtual destructor" при включении -Wall

W>Особенности:

W>1) Просто добавить виртуальные деструкторы — нельзя. Это by design. Нигде в том коде невозможно удалить объект такого класса через delete на базовый указатель.

Интересно знать, в чём смысл такого дизайна? И почему нельзя просто добавить.
Это автомагически добавит ранее отсутствующую таблицу виртуальных функций на которой хотели сэкономить?
Как у микрософта, __declspec(novtable)?

W>Есть ли еще какой-то способ подавить этот warning?


Через прагму запретить все варнинги для данной одной конкретной строчки (где он возникает) ?
Только боюсь не выйдет, т.к. ранние версии GCC не умели _Pragma("GCC diagnostic ignore \"что-надо"").
И через #pragma не умели.
Re[2]: Подавить warning в древнем GCC
От: wander  
Дата: 20.01.24 19:32
Оценка:
Здравствуйте, fk0, Вы писали:

fk0> Интересно знать, в чём смысл такого дизайна? И почему нельзя просто добавить.

Этот код — часть большого plugin-based проекта.

Эти интерфейсы — это интерфейсы для написания плагинов с их использованием. Плагины могут быть написаны с
использованием разных компиляторов и даже разных языков (порядок работы чем-то напоминает COM).
Добавляемый в такой интерфейс виртуальный деструктор вынужден быть inline, а это при такой организации кода
недопустимо (я думаю вы и сами уже догадались почему).
Для разрушения объектов предусмотрена специальная функция-деструктор, которая гарантированно уничтожит объект
там же, где он создавался.

fk0> Через прагму запретить все варнинги для данной одной конкретной строчки (где он возникает) ?

fk0>Только боюсь не выйдет, т.к. ранние версии GCC не умели _Pragma("GCC diagnostic ignore \"что-надо"").
fk0>И через #pragma не умели.

Да, это в 4.1.3 не работает.
Re[3]: Подавить warning в древнем GCC
От: fk0 Россия https://fk0.name
Дата: 24.01.24 11:08
Оценка:
Здравствуйте, wander, Вы писали:

fk0>> Интересно знать, в чём смысл такого дизайна? И почему нельзя просто добавить.

W>Этот код — часть большого plugin-based проекта.

W>Эти интерфейсы — это интерфейсы для написания плагинов с их использованием. Плагины могут быть написаны с

W>использованием разных компиляторов и даже разных языков (порядок работы чем-то напоминает COM).
W>Добавляемый в такой интерфейс виртуальный деструктор вынужден быть inline,

А вот с этого момента поподробнее. Кто его вынуждает быть inline и каким способом???
В C++ такого не предусмотрено, чтоб кого-то вынуждать.

W>Для разрушения объектов предусмотрена специальная функция-деструктор, которая гарантированно уничтожит объект

W>там же, где он создавался.

В каком смысле "там же"? И чем обычный деструктор кардинально отличается от спец. функции?
Мне кажется с точки зрения компилятора -- ни чем. В конечном счёте функция как функция. Когда
уже до машинного кода дошло.

Мне кажется, здесь речь о каком-то архитектурном паттерне, который нарушает стандарт в каких-то
частях, но пытаться что-то изменить уже поздно. Но я никак не понимаю, что за паттерн.
Re[4]: Подавить warning в древнем GCC
От: wander  
Дата: 25.01.24 14:23
Оценка:
Здравствуйте, fk0, Вы писали:

fk0> А вот с этого момента поподробнее. Кто его вынуждает быть inline и каким способом???

fk0>В C++ такого не предусмотрено, чтоб кого-то вынуждать.

В C++ нет интерфейсов. Интерфейсы в C++ — это классы с чистовиртуальными функциями.
Но деструктор отличается от остальных функций тем, что у него, даже если он чистовиртуальный, должна быть реализация.

Если нужен виртуальный деструктор в интерфейсном хедере, то есть два пути:
1) либо мы предоставляем реализацию деструктора в inline прямо в хедере,
2) либо обязать тех, кто реализует интерфейс, создавать эту реализацию в своей какой-то единице трансляции, но это неудобно.
Скажем так, из соображений удобства использования, деструктор, если он виртуальный, вынужден быть inline.

А выход простой из этого. Виртуальные деструкторы вообще не нужны. Мы все равно благодаря Release не удаляем через явный delete ничего.
А Release сама по себе виртуальная достаточно, чтобы знать фактический тип наследника и правильно его уничтожить.

fk0> В каком смысле "там же"? И чем обычный деструктор кардинально отличается от спец. функции?

fk0>Мне кажется с точки зрения компилятора -- ни чем. В конечном счёте функция как функция. Когда
fk0>уже до машинного кода дошло.

В том же модуле, с использованием того же аллокатора и т.д. Удалять в одном модуле через delete объект, который создал другой модуль (возможно на другом языке) — это неправильно.
А вот виртуальная функция Release, которая имплементирована в другом модуле — другое дело. При этом ее вызов никак не привязан к внутреннему
ABI модуля (в отличие от вызова delete, которому нужно ABI конкретной реализации C++).
_____
UPD. Добавлю, что если мы делаем "заголовочный файл" интерфейса для другого языка (отличного от C++), то деструктор там выглядит чужеродно.
А коль скоро он не нужен для работы, то и писать его и прокидывать в слои совместимости с другими языками, не нужно.

Ну вот посмотри на интерфейсы COM. Там тоже нет виртуальных деструкторов. Мотивация точно такая же.

fk0> Но я никак не понимаю, что за паттерн.


А я не пойму к чему эти вопросы?
Хочешь ревью этой системы провести? Или что?
Отредактировано 25.01.2024 15:16 wander . Предыдущая версия . Еще …
Отредактировано 25.01.2024 14:29 wander . Предыдущая версия .
Re[5]: Подавить warning в древнем GCC
От: fk0 Россия https://fk0.name
Дата: 25.01.24 23:23
Оценка:
Здравствуйте, wander, Вы писали:

W>Здравствуйте, fk0, Вы писали:


fk0>> А вот с этого момента поподробнее. Кто его вынуждает быть inline и каким способом???

fk0>>В C++ такого не предусмотрено, чтоб кого-то вынуждать.

W>В C++ нет интерфейсов. Интерфейсы в C++ — это классы с чистовиртуальными функциями.

W>Но деструктор отличается от остальных функций тем, что у него, даже если он чистовиртуальный, должна быть реализация.

W>Если нужен виртуальный деструктор в интерфейсном хедере, то есть два пути:

W>1) либо мы предоставляем реализацию деструктора в inline прямо в хедере,
W>2) либо обязать тех, кто реализует интерфейс, создавать эту реализацию в своей какой-то единице трансляции, но это неудобно.
W>Скажем так, из соображений удобства использования, деструктор, если он виртуальный, вынужден быть inline.

Надуманно. На самом деле 3) оставляем на совести того, кто пишет код.
Делать или не делать inline -- никто не заставляет.

W>А выход простой из этого. Виртуальные деструкторы вообще не нужны. Мы все равно благодаря Release не удаляем через явный delete ничего.

W>А Release сама по себе виртуальная достаточно, чтобы знать фактический тип наследника и правильно его уничтожить.

Подразумевается, вызов instance->Release() в том числе и освобождает память?

Ну отлично. Виртуальный деструктор в данном случае действительно не нужен, но его
присутствие никому не мешает же, чтоб прямо осознанно бороться с ним. Проще его оставить,
потому, что в той системе программировния откуда он появляется, его отсутствие скорей
странно и является потенциальным источником ошибок.

В конце концов, ведь в C++-коде, не выходя за рамки C++ и без COM-подобных интерфейсов
можно просто по-тихому взять и унаследовать класс. И начать пользоваться каким-то
странным образом и вне рамок изначально запланированного сценария. Конечно можно сказать,
мол не стоит так делать, но с другой стороны явно никто же не запрещает и получиться
так может случайно и очень неочевидным образом. В том и смысл навязываемых в языке
C++ ограничений, чтоб даже в таких случаях сохранить работоспособность в противовес
утечкам ресурсов, падениям с невообразимыми бэктрейсами и т.п.

W>А коль скоро он не нужен для работы, то и писать его и прокидывать в слои совместимости с другими языками, не нужно.

W>Ну вот посмотри на интерфейсы COM. Там тоже нет виртуальных деструкторов. Мотивация точно такая же.

Там управление памяться делегировано самому объекту, который не копируемый и не перемещаемый, потому и так.

fk0>> Но я никак не понимаю, что за паттерн.

W>А я не пойму к чему эти вопросы?
W>Хочешь ревью этой системы провести? Или что?

Я хочу сказать, борьба с виртуальным деструктором -- странное дело.
Re[6]: Подавить warning в древнем GCC
От: wander  
Дата: 26.01.24 08:04
Оценка:
Здравствуйте, fk0, Вы писали:

fk0> Надуманно. На самом деле 3) оставляем на совести того, кто пишет код.

Нет. Тут не все так просто.

fk0> Подразумевается, вызов instance->Release() в том числе и освобождает память?

Конечно. Тут довольно сложно сделать иначе, учитывая все вводные.
Когда я в первом ответе упомянул COM, это было не просто так.

fk0> Там управление памяться делегировано самому объекту, который не копируемый и не перемещаемый, потому и так.

Тут тоже так.

fk0> Я хочу сказать, борьба с виртуальным деструктором -- странное дело.

Нет. Тут есть подводные камни. На самом деле я даже мог бы это доказать, но это приведет к написанию статьи.
Слишком много времени нужно будет потратить, а профита от этого для меня нет.
Может быть чуть позже найду время и напишу, но явно не прямо сейчас.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.