Вопросы про исключения в деструкторах
От: Максим Рогожин Россия  
Дата: 26.04.18 16:11
Оценка:
Привет!

Деструкторы не должны кидать исключения.

Вопрос 1: Как этого добиться, ведь даже если мы сами не кидаем исключение, его может кинуть какой-то метод/функция/оператор, который мы зовем в деструкторе?
Вопрос 2: В книге "Решение сложных задач на С++" Герб Саттер отмечает, что неплохо бы все деструкторы писать так ~SomeClass() throw(). Но я редко вижу такое объявление деструкторов в проектах. Так все таки нужно или нет писать деструкторы со спецификацией throw()?
Re: Вопросы про исключения в деструкторах
От: Stanislav V. Zudin Россия  
Дата: 26.04.18 16:22
Оценка: 2 (1) +2
Здравствуйте, Максим Рогожин, Вы писали:

МР>Деструкторы не должны кидать исключения.


МР>Вопрос 1: Как этого добиться, ведь даже если мы сами не кидаем исключение, его может кинуть какой-то метод/функция/оператор, который мы зовем в деструкторе?


Видимо не вызывать того, что может кинуть исключение.
Либо, если не обойтись, то оборачивать в try/catch.

МР>Вопрос 2: В книге "Решение сложных задач на С++" Герб Саттер отмечает, что неплохо бы все деструкторы писать так ~SomeClass() throw(). Но я редко вижу такое объявление деструкторов в проектах. Так все таки нужно или нет писать деструкторы со спецификацией throw()?


throw() считается deprecated. Так что этот совет можно проигнорировать.
Читать про noexcept.
_____________________
С уважением,
Stanislav V. Zudin
Re: Вопросы про исключения в деструкторах
От: Alexander G Украина  
Дата: 26.04.18 16:23
Оценка:
Здравствуйте, Максим Рогожин,

Деструкторы по умолчанию noexcept, так что бросать вообще из них нельзя, ну или писать явно noexcept(false) если с этим жить.

МР>Вопрос 1: Как этого добиться, ведь даже если мы сами не кидаем исключение, его может кинуть какой-то метод/функция/оператор, который мы зовем в деструкторе?


Не делать ничего в деструкторах.

МР>Вопрос 2: В книге "Решение сложных задач на С++" Герб Саттер отмечает, что неплохо бы все деструкторы писать так ~SomeClass() throw(). Но я редко вижу такое объявление деструкторов в проектах. Так все таки нужно или нет писать деструкторы со спецификацией throw()?


throw() уже deprecated, да, его никто не писал, и не нужно начинать.
Русский военный корабль идёт ко дну!
Re: Вопросы про исключения в деструкторах
От: Pzz Россия https://github.com/alexpevzner
Дата: 26.04.18 16:39
Оценка: 2 (1)
Здравствуйте, Максим Рогожин, Вы писали:

МР>Вопрос 1: Как этого добиться, ведь даже если мы сами не кидаем исключение, его может кинуть какой-то метод/функция/оператор, который мы зовем в деструкторе?


Ловить и обрабатывать локально.
Re[2]: Вопросы про исключения в деструкторах
От: Максим Рогожин Россия  
Дата: 26.04.18 16:42
Оценка:
Здравствуйте, Alexander G, Вы писали:


МР>>Вопрос 1: Как этого добиться, ведь даже если мы сами не кидаем исключение, его может кинуть какой-то метод/функция/оператор, который мы зовем в деструкторе?

AG>Не делать ничего в деструкторах.

Ну вот надо например в деструкторе позвать closeDataBaseConnection(), а этот метод исключение кидать может. Как делать?
Re[2]: Вопросы про исключения в деструкторах
От: Максим Рогожин Россия  
Дата: 26.04.18 16:58
Оценка:
Здравствуйте, Pzz, Вы писали:

Pzz>Здравствуйте, Максим Рогожин, Вы писали:


МР>>Вопрос 1: Как этого добиться, ведь даже если мы сами не кидаем исключение, его может кинуть какой-то метод/функция/оператор, который мы зовем в деструкторе?


Pzz>Ловить и обрабатывать локально.


Если в деструкторе несколько разных функций вызывается, которые в свою очередь другие функции зовут, да еще учесть, что со временем реализация этих функций может измениться (сейчас не бросают исключение, но в будущем могут бросать), то получается, что надо сразу весь код деструктора брать в блок try-catch?

~SomeClass() {
   try {
      // здесь код деструктора
   } catch(...) {
      // например, выводим сообщение в лог-файл?
   }
}


Так?
Re[3]: Вопросы про исключения в деструкторах
От: Pzz Россия https://github.com/alexpevzner
Дата: 26.04.18 17:09
Оценка: +1
Здравствуйте, Максим Рогожин, Вы писали:

МР>Если в деструкторе несколько разных функций вызывается, которые в свою очередь другие функции зовут, да еще учесть, что со временем реализация этих функций может измениться (сейчас не бросают исключение, но в будущем могут бросать), то получается, что надо сразу весь код деструктора брать в блок try-catch?


А объект после пойманного и отправленного в лог исключения будет "разобран"? Не получится так, что останутся неосвобожденные ресурсы, до освобождения которых просто не дошло дело?
Re[4]: Вопросы про исключения в деструкторах
От: Максим Рогожин Россия  
Дата: 26.04.18 17:22
Оценка:
Здравствуйте, Pzz, Вы писали:

Pzz>А объект после пойманного и отправленного в лог исключения будет "разобран"? Не получится так, что останутся неосвобожденные ресурсы, до освобождения которых просто не дошло дело?


Кстати, да, получится!) Так я вот и спрашиваю что делать с исключениями в деструкторах)
Re[5]: Вопросы про исключения в деструкторах
От: Pzz Россия https://github.com/alexpevzner
Дата: 26.04.18 17:24
Оценка:
Здравствуйте, Максим Рогожин, Вы писали:

Pzz>>А объект после пойманного и отправленного в лог исключения будет "разобран"? Не получится так, что останутся неосвобожденные ресурсы, до освобождения которых просто не дошло дело?


МР>Кстати, да, получится!) Так я вот и спрашиваю что делать с исключениями в деструкторах)


Ловить и обрабатывать локально. Не прятать, кокетливо обернув в лог, который никто не читает, а обрабатывать по существу
Re: Вопросы про исключения в деструкторах
От: jazzer Россия Skype: enerjazzer
Дата: 27.04.18 04:40
Оценка: 2 (1)
Здравствуйте, Максим Рогожин, Вы писали:

МР>Привет!


МР>Деструкторы не должны кидать исключения.


МР>Вопрос 1: Как этого добиться, ведь даже если мы сами не кидаем исключение, его может кинуть какой-то метод/функция/оператор, который мы зовем в деструкторе?


Можно проверять каждое выражение на noexcept, если хочется хардкора.
Типа
static_assert(noexcept(c=a+b),"should be noexcept);
c=a+b;

Но это хардкор и не всегда имеет смысл — ведь ты заранее можешь знать, что некоторые вызовы не сгенерируют исключений, даже если они и не объявлены noexcept — просто потому что ты уверен в состоянии и аргументах.
Например, если ты проверил индекс, что он точно не вылетит за пределы вектора, то вызов vector::at точно не сгенерирует исключения, несмотря на то, что в других случаях он может и поэтому, естественно, не объявлен noexcept.

МР>Вопрос 2: В книге "Решение сложных задач на С++" Герб Саттер отмечает, что неплохо бы все деструкторы писать так ~SomeClass() throw(). Но я редко вижу такое объявление деструкторов в проектах. Так все таки нужно или нет писать деструкторы со спецификацией throw()?


Книга Саттера — про С++98.
Начиная с С++11 все деструкторы noexcept по умолчанию. Т.е. если ты собираешься что-то бросать из деструктора, ты явно должен объявить его с noexcept(false), в противном случае ничего делать не надо.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[3]: Вопросы про исключения в деструкторах
От: Maniacal Россия  
Дата: 27.04.18 07:49
Оценка: +1
Здравствуйте, Максим Рогожин, Вы писали:

МР>Ну вот надо например в деструкторе позвать closeDataBaseConnection(), а этот метод исключение кидать может. Как делать?


try { closeDataBaseConnection(); } catch(...) {}
Re[3]: Вопросы про исключения в деструкторах
От: N. I.  
Дата: 27.04.18 11:00
Оценка: 2 (1)
Максим Рогожин:

МР>Ну вот надо например в деструкторе позвать closeDataBaseConnection(), а этот метод исключение кидать может. Как делать?


Зависит от соглашений по обработке исключений в конкретно взятом проекте. Некоторые соглашения могут подразумевать, что всякая функция, освобождающая ресурс, обязана быть noexcept, и тогда бросающего closeDataBaseConnection в программе не должно существовать в принципе. Если же closeDataBaseConnection — это часть чужой либы, то тут возможны два случая:

1) если closeDataBaseConnection не умеет гарантированно чистить все локальные ресурсы соединения (на стороне, вызвавшей closeDataBaseConnection), то либа отправляется на помойку и заменяется более кошерной;

2) если closeDataBaseConnection гарантированно чистит все локальные ресурсы соединения, но может сообщать о каких-то проблемах путём бросания исключений, то closeDataBaseConnection оборачивается в noexcept функцию, в которую опционально может передаваться callback обработчик ошибок (опять же небросающий).
Re[2]: Вопросы про исключения в деструкторах
От: Максим Рогожин Россия  
Дата: 27.04.18 12:34
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Книга Саттера — про С++98.


А есть ли более современные книги для углубленного изучения базового С++ ?
Re[3]: Вопросы про исключения в деструкторах
От: jazzer Россия Skype: enerjazzer
Дата: 27.04.18 15:59
Оценка:
Здравствуйте, Максим Рогожин, Вы писали:

МР>Здравствуйте, jazzer, Вы писали:


J>>Книга Саттера — про С++98.


МР>А есть ли более современные книги для углубленного изучения базового С++ ?


Есть Effective Modern C++ Майерса (вот по-русски: https://www.ozon.ru/context/detail/id/34747131/)
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[4]: Вопросы про исключения в деструкторах
От: Максим Рогожин Россия  
Дата: 27.04.18 16:33
Оценка:
Здравствуйте, jazzer, Вы писали:

МР>>А есть ли более современные книги для углубленного изучения базового С++ ?


J>Есть Effective Modern C++ Майерса (вот по-русски: https://www.ozon.ru/context/detail/id/34747131/)


Я посмотрел содержание — эта книга по новым фичам C++, а мне нужны базовые, которые описываются, например, в "Effective C++" Мейерса — но только эта книга тоже выпущена лет 15 назад. Стоит читать ее сейчас или она уже устарела?
Re[3]: Вопросы про исключения в деструкторах
От: reversecode google
Дата: 27.04.18 16:40
Оценка: 9 (1) +1
вы можете изучить весь английский алфавит, даже выучить много слов, но толку от этого будет мало
в любом деле важен опыт
вы ядро линукса читаете легко ?
а в куте можете быстро разобраться ?
итд
тогда можете хоть все книги мира по С++ перечитать, толку не будет
Re[2]: Вопросы про исключения в деструкторах
От: Constructor  
Дата: 27.04.18 19:02
Оценка: +1
Здравствуйте, jazzer, Вы писали:

МР>>Вопрос 2: В книге "Решение сложных задач на С++" Герб Саттер отмечает, что неплохо бы все деструкторы писать так ~SomeClass() throw(). Но я редко вижу такое объявление деструкторов в проектах. Так все таки нужно или нет писать деструкторы со спецификацией throw()?


J>Книга Саттера — про С++98.

J>Начиная с С++11 все деструкторы noexcept по умолчанию. Т.е. если ты собираешься что-то бросать из деструктора, ты явно должен объявить его с noexcept(false), в противном случае ничего делать не надо.

Это не совсем так. Если у класса есть член и/или базовый класс, деструктор которого явно помечен noexcept(false), то неявная пометка noexcept(true) с деструктора такого класса снимается:
#include <iostream>
#include <exception>
#include <stdexcept>


struct Bar
{
    ~Bar() noexcept(false)
    {
        std::cout << "Bar()::~Bar()" << std::endl;
        throw std::runtime_error{"Error in destructor!"};
    }
};

struct Foo
{
    Bar bar;

    ~Foo()
    {
        std::cout << "Foo()::~Foo()" << std::endl;
    }
};


void terminate_handler()
{
    std::cout << "Termination..." << std::endl;
    std::abort();
}


int main()
try
{
    std::set_terminate(terminate_handler);
    
    (void)Foo{};
}
catch (const std::exception& exception)
{
    std::cout << "Exception: " << exception.what() << std::endl;
}

Разумеется, если деструктору класса Foo добавить явный спецификатор noexcept/noexcept(true), то будет вызван terminate_handler (и в том, и в другом случаях).
Поэтому, возможно, совет Саттера все еще актуален в какой-то степени (хотя вместо deprecated throw() [который приравнен к noexcept(true), начиная с C++17] сейчас, конечно, лучше писать noexcept или noexcept(true)), ему стоит следовать, чтобы избежать проблем при потенциальном рефакторинге (в ходе которого у класса могут появиться члены и/или базовые классы, деструктор которых помечен noexcept(false)).
Re[5]: Вопросы про исключения в деструкторах
От: wander  
Дата: 06.05.18 13:17
Оценка:
Здравствуйте, Максим Рогожин, Вы писали:

МР>...в "Effective C++" Мейерса — но только эта книга тоже выпущена лет 15 назад. Стоит читать ее сейчас или она уже устарела?


Стоит, просто с поправками на современное состояние дел.
Поправок таких будет не очень много.
Основные отличия можно посмотреть в C++11FAQ Страуструпа.
Re[2]: Вопросы про исключения в деструкторах
От: onehalf3554 Верблюд  
Дата: 28.05.18 10:55
Оценка:
Здравствуйте, Stanislav V. Zudin, Вы писали:

SVZ>Здравствуйте, Максим Рогожин, Вы писали:


МР>>Деструкторы не должны кидать исключения.


МР>>Вопрос 1: Как этого добиться, ведь даже если мы сами не кидаем исключение, его может кинуть какой-то метод/функция/оператор, который мы зовем в деструкторе?


SVZ>Видимо не вызывать того, что может кинуть исключение.

SVZ>Либо, если не обойтись, то оборачивать в try/catch.

МР>>Вопрос 2: В книге "Решение сложных задач на С++" Герб Саттер отмечает, что неплохо бы все деструкторы писать так ~SomeClass() throw(). Но я редко вижу такое объявление деструкторов в проектах. Так все таки нужно или нет писать деструкторы со спецификацией throw()?


SVZ>throw() считается deprecated. Так что этот совет можно проигнорировать.

SVZ>Читать про noexcept.

Мне если честно не очень понятно почему в 21 веке, когда наши космические корабли бороздят...,
у людей всё ещё возникают такие вопросы.
Можно ведь реализовать метод в котором будут находится все страшные и ужасные разбойники Бармалеи:
void
someclass:: 
destructor_realisator()
{
 try{

  //тут значит много разного 
  //  проверки, освобождение занятых ресурсов, 
  //  вспоминаем  старую добрую идиому RAII
  // 

  }
 catch(...)
 {
   //чтото вроде log-файла пишем кстати есть ньюансы 
   1)код запросто может сам вызвать исключение
   2)информативность подобного лога вызывает сомнения.
    Но это не суть важно, ведь мы хитрые пацаны. 
 }
}
//поэтому:)

~someclass()
{
  try
  {
    destructor_realisator();    
  }
  catch(...)
  {

  }
}


Както так. я делал когда был студентом. Потом стал делать намного лучше, о это уже совсем другая история
Как давно я здесь небыл Родной rsdn
Если карта не соответствует местности доверяй местности
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.