Здравствуйте, anton_t, Вы писали:
_>Здравствуйте, remark, Вы писали:
R>>Здравствуйте, anton_t, Вы писали:
_>>>Здравствуйте, Cyberax, Вы писали:
C>>>>sch wrote:
>>>>> Соответственно, больше всего пугает самое новое и необычное: например,
>>>>> чаще всего у C++ программистов нарекания вызывает GC из .NET. /Боже
>>>>> мой, он будет лазить по моим структурам когда ему захочется, и будет
>>>>> освобождать память! Сам!/
C>>>>Это-то фигня. Больше всего раздражает, что GC уничтожает память
C>>>>недетерминировано. А значит RAII и подобные идиомы не проходят.
_>>>Касательно RAII: что вы делаете с исключениями в деструкторах?
R>>Если я правильно понял, вопрос касательно С++.
R>>В С++ исключения в деструкторах не генерируют.
_>А если их генерирует вызываемая в деструкторе функция?
В С++ такие функции не вызываются в деструкторе. Основной вариант.
Либо исключение ловятся и преобразуется в какую-либо другую форму. Практически не применяемый вариант.
Либо, если это не принципиальная функция, типа логирования, то исключения подавляются.
Здравствуйте, anton_t, Вы писали:
_>Здравствуйте, _nn_, Вы писали:
__>>Здравствуйте, anton_t, Вы писали:
__>><skip/>
_>>>А если их генерирует вызываемая в деструкторе функция?
__>>После того как вы стреляте в ногу себе, вы еще хотите и ходить ?
__>>Просто оберните все в try-catch(...) и исключение не вылетит.
_>Понятно, глотать и логгировать. Я думал может кто что-нибудь умнее знает. А с "стреляете в ногу я не согласен". Разве ошибка при освобождении ресурса это такое уж редкое явление?
Может это и не редкое явление, но вызывающий код оно не интересует. Интерфейс деструктора — "Освободить ресурс. Точка.", а не "Возможно освободить ресурс. Если не получиться, то сообщить мне — я сам попробую с этим что-нибудь сделать". Суть в том, что вызывающий код в подавляющем большинстве случаев ничего осмысленного сделать не сможет. Что можно сделать с ресурсом, который больше не нужен, но освободить его не получается?
Можно, конечно, положить ресурс в специальный список для таких ресурсов. И потом попробовать его освободить ещё раз через некоторое время. Но во-первых, это попахивает галиматьёй. А во-вторых, операция добавления в список тоже может провалиться.
Плюс к этому, если операция удаления/отката/освобождения может проваливаться, то в такой ситуации теоретически нельзя строить надёжные системы. Например смотри алгоритм two-phase commit.
А так, в принципе, если хочется "что-нибудь умнее", то в С++ не проблема повторить механизм вложенных исключений. Можно нагородить что-нибудь вроде такого:
class exception
{
public:
typedef shared_ptr<exception> exception_ptr;
static void do_throw (exception_ptr ex)
{
if (0 == thread_ex)
{
thread_ex = ex.get();
throw ex;
}
else
{
thread_ex->add(ex);
}
}
~exception()
{
if (thread_ex == this)
thread_ex = 0;
}
private:
static __declspec(thread) exception* thread_ex;
std::list<exception_ptr> inners;
void add(exception_ptr inner)
{
inners.push_back(inner);
}
};
Только это никак не отменяет того, что особо осмысленные действия сложно сделать с такими исключениями.
А так же вопрос — что делать, если при конструировании исключения, или при добавлении исключения как вложенного происходит ошибка? Как языки со вложенными исключениями на это реагируют? Я думаю ничего осмысленного нет и там...