Re[25]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: drol  
Дата: 07.08.08 11:43
Оценка: +1
Здравствуйте, VoidEx, Вы писали:

S>>Какие проблемы?


VE>Вот и я хочу узнать, какие?


VE>
VE>try
VE>{
VE>  File file1( ... );
VE>  try
VE>  {
VE>    File file2( ... );
VE>    try
VE>    {
VE>      // ...
VE>    }
VE>    catch ( ... ) {}
VE>  }
VE>  catch ( ... ) {}
VE>}
VE>catch ( ... ) {}
VE>


Те же самые. Деструкторы не могут бросать исключения. Посему об ошибках I/O при закрытии файла вызывающий код никогда не узнает.
Re[26]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 07.08.08 11:48
Оценка:
Здравствуйте, drol, Вы писали:

D>Те же самые. Деструкторы не могут бросать исключения. Посему об ошибках I/O при закрытии файла вызывающий код никогда не узнает.


А теперь вопрос: что важнее -- знать про первое исключение, которое спровоцировало раскрутку стека (подход C++), или последнее исключение, которое было порождено в результате раскрутки стека (подхож C#)?


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[18]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 07.08.08 11:52
Оценка: :)
Здравствуйте, Sinclair, Вы писали:

S>Нам вообще все равно, где возникло исключение: главное, что мы отличаем ситуацию успешной записи от неудачи. В C++ придется делать flush руками, потому что попытка сделать flush в деструкторе приведет к проглоту исключения.


Если нам все равно и главное знать про успех/неудачу, то какая разница, что в C++ flush-ширование в деструкторе будет проходить с проглатыванием исключения?


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[19]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: VoidEx  
Дата: 07.08.08 12:05
Оценка:
Здравствуйте, eao197, Вы писали:

E>Если нам все равно и главное знать про успех/неудачу, то какая разница, что в C++ flush-ширование в деструкторе будет проходить с проглатыванием исключения?


Ну так в Си++ деструктор не выкинет ничего, и будет вроде всё хорошо.
А там исключение вылетит, просто возможно оно затрёт предыдущее.
Re[27]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 07.08.08 12:11
Оценка: -1
Здравствуйте, eao197, Вы писали:

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


D>>Те же самые. Деструкторы не могут бросать исключения. Посему об ошибках I/O при закрытии файла вызывающий код никогда не узнает.


E>А теперь вопрос: что важнее -- знать про первое исключение, которое спровоцировало раскрутку стека (подход C++), или последнее исключение, которое было порождено в результате раскрутки стека (подхож C#)?


Откройте для себя InnerException
Re[28]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: VoidEx  
Дата: 07.08.08 12:12
Оценка: +1
Здравствуйте, gandjustas, Вы писали:

G>Откройте для себя InnerException


Причём оно тут?
Re[18]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: Cyberax Марс  
Дата: 07.08.08 12:22
Оценка:
Здравствуйте, Sinclair, Вы писали:

C>>Кто мне мешает сделать то же самое в C++?

S>То, что после terminate ничего сделать уже нельзя.
А зачем мне делать terminate?

S>Еще раз поясняю: обычно никакого интереса к повторным исключениям у вызывающего нет. Вот, допустим, код устроен примерно таким образом:

S>
S>public bool ProcessJob(job j)
S>{
S>  try
S>  {
S>    using(Stream s = GetStreamForJob(j))
S>      WriteData(s);
S>    return true;
S>  }
S>  catch (Exception e)
S>  {
S>    return false;
S>  }
S>}
S>public bool ProcessJobStep(JobQueue q)
S>{
S>  Job j = q.Dequeue();
S>  j.Attempts++;
S>  if (!ProcessJob(j))
S>    q.Enqueue(); // return to queue for another attempt
S>}
S>


bool process_job(job j)
{
  try
  {
     stream s(get_stream_for_job(j));
     write_data(s);
     return true;
  } catch(...) {return false;}
}

И в деструкторе stream просто не бросаем повторное исключение.

S>Совершенно нармальная ситуация. Нам не нужно беспокоиться, что деструктор стрима не сможет сделать flush. Значит, мы можем перейти от небуферизованного стрима к буферизованному. Нам вообще все равно, где возникло исключение: главное, что мы отличаем ситуацию успешной записи от неудачи. В C++ придется делать flush руками, потому что попытка сделать flush в деструкторе приведет к проглоту исключения.

Мы можем выпускать исключение, если в данный момент не активно другое. Как вариант — можно сделать подход с флагами:

bool process_job(job j)
{
     stream *str=get_stream_for_job(j);

     stream_handle hndl(str);
     write_data(hndl);

     return str->is_error_flag_set();
}


Конкретно второй вариант мне нравится больше.
Sapienti sat!
Re[18]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: Cyberax Марс  
Дата: 07.08.08 12:24
Оценка: 1 (1) +1
Здравствуйте, drol, Вы писали:

C>>Кто мне мешает сделать то же самое в C++?

D>Как вызывающий деструкторы код узнает о том, что ж случилось и нужно реагировать, если деструкторы не могут бросать исключения ??? Ну что непонятного-то ???
Разными путями — установкой флагов, например. Что, у нас нет ничего кроме исключений?

Вообще, дизайн с броском исключений в деструкторах — кривой по своей сути.

D>*И напоследок. Вы топик вообще читали, уважаемый ??? Я уже раза три разжёвывал тему. Мне обязательно это делать для каждого очередного "чукчи-писателя" зашедшего на огонёк ???

Читал, читал. Я про работу исключений вообще знаю в глубоких ассемблерных подробностях.
Sapienti sat!
Re[25]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: drol  
Дата: 07.08.08 12:49
Оценка:
Здравствуйте, CreatorCray, Вы писали:

D>>Rationale этого решения стандарта, лично я, внятно изложить не могу

CC>Например как добивать локальный объект, который при выходе из функции в своем деструкторе вдруг кинул исключение? По идее это означает что деструкция не была полностью завершена, объект не был корректно удален, но, тем не менее выход из функции уже его недобитые останки закопал. Что делать? Как его добить в такой ситуации?

Не годится. Один-то уровень исключений из деструктора я ведь могу организовать. А там всё точно так же: недобитый объект, все дела... Однако не мешает

Я всё-таки полагаю, что смотреть надо в сторону стека и расположения объектов на нём. В особенности собственно исключения и локальных объектов создаваемых/уничтожаемых вызываемыми при раскрутке деструкторами.
Re[23]: Exception в Finally
От: SE Украина  
Дата: 07.08.08 12:56
Оценка:
Здравствуйте, SE, Вы писали:

SE>На самом деле есть "последний". Не получите вы цепочку, и не надейтесь.


Может быть уважаемый Sinclair вместо раздачи минусов направо и налево объяснит, с чем он в примере не согласен, и каким образом можно восстановить цепочку исключений случившихся в using после исключения в методе Dispose?
Я с благодарностью выслушаю, как это можно сделать. А пример кода был бы просто бальзамом на душу.
Re[20]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 07.08.08 13:07
Оценка:
Здравствуйте, VoidEx, Вы писали:

E>>Если нам все равно и главное знать про успех/неудачу, то какая разница, что в C++ flush-ширование в деструкторе будет проходить с проглатыванием исключения?


VE>Ну так в Си++ деструктор не выкинет ничего, и будет вроде всё хорошо.

VE>А там исключение вылетит, просто возможно оно затрёт предыдущее.

Упс... Ступил


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[19]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: drol  
Дата: 07.08.08 13:09
Оценка: 1 (1) +2 -1
Здравствуйте, Cyberax, Вы писали:

C>>>Кто мне мешает сделать то же самое в C++?

D>>Как вызывающий деструкторы код узнает о том, что ж случилось и нужно реагировать, если деструкторы не могут бросать исключения ??? Ну что непонятного-то ???
C>Разными путями — установкой флагов, например. Что, у нас нет ничего кроме исключений?

Просто прелестно. 2008 год на дворе, а у нас глобальные флаги и GetError() во всей своей красе... А люди-то парились, исключения городили... А ну нафиг всё, ведь есть флаги!!!

C>Вообще, дизайн с броском исключений в деструкторах — кривой по своей сути.


Разумеется! Я совершенно с Вами согласен. И именно поэтому в нормальных языках типа C# сделаны try/finally/using/IDisposable и GC впридачу. Бо не надо мешать задачу управления циклом жизни объекта в одну кучу с задачей управления памятью, занимаемой этим самым объектом.
Деструктор/finalizer не должен бросать исключения, их должен бросать совершенно обычный метод, предназначенный для закрытия ресурса и используемый в нормальном контексте исполнения программы. В случае C# это IDisposable.Dispose()

C>Я про работу исключений вообще знаю в глубоких ассемблерных подробностях.


Тогда Вы, наверняка, сумеете ответить на мой вопрос о rationale положений стандарта о вызове terminate(), в случае исключения при развёртке стека. Или не сможете ?
Re[26]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: CreatorCray  
Дата: 07.08.08 13:14
Оценка:
Здравствуйте, drol, Вы писали:

D>Не годится. Один-то уровень исключений из деструктора я ведь могу организовать. А там всё точно так же: недобитый объект, все дела... Однако не мешает

D>Я всё-таки полагаю, что смотреть надо в сторону стека и расположения объектов на нём. В особенности собственно исключения и локальных объектов создаваемых/уничтожаемых вызываемыми при раскрутке деструкторами.
Ты вопрос то понял?
Вопрос в том, что вот покинул объект область видимости и сработал его деструктор. А в деструкторе на полдороги вылетело исключение и некоторые нужные шаги в деструкторе не выполнились. Ты это исключение где то выше поймал и как то обработал. Как теперь "додеструктить" объект то?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Re[20]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: Cyberax Марс  
Дата: 07.08.08 13:14
Оценка: :)
Здравствуйте, drol, Вы писали:

C>>Разными путями — установкой флагов, например. Что, у нас нет ничего кроме исключений?

D>Просто прелестно. 2008 год на дворе, а у нас глобальные флаги и GetError() во всей своей красе... А люди-то парились, исключения городили... А ну нафиг всё, ведь есть флаги!!!
Ну флаги. И что дальше? Что делать, если они лучше всего подходят для решения проблемы...

D>Разумеется! Я совершенно с Вами согласен. И именно поэтому в нормальных языках типа C# сделаны try/finally/using/IDisposable и GC впридачу. Бо не надо мешать задачу управления циклом жизни объекта в одну кучу с задачей управления памятью, занимаемой этим самым объектом.

try..finally — это кривой аналог деструктора. Так что бросок исключения из finally — это тот же самый кривой дизайн, вид сбоку.

C>>Я про работу исключений вообще знаю в глубоких ассемблерных подробностях.

D>Тогда Вы, наверняка, сумеете ответить на мой вопрос о rationale положений стандарта о вызове terminate(), в случае исключения при развёртке стека. Или не сможете ?
Смогу. Оно нужно для гарантии того, что изначальное исключение не будет молчаливо затёрто.
Sapienti sat!
Re[20]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 07.08.08 13:39
Оценка:
Здравствуйте, drol, Вы писали:

D>Просто прелестно. 2008 год на дворе, а у нас глобальные флаги и GetError() во всей своей красе... А люди-то парились, исключения городили... А ну нафиг всё, ведь есть флаги!!!


Есть, по крайней мере, одна хорошая C++ библиотека, которая использует uncaught_exception в деструкторах для того, чтобы принять решение о том, можно ли порождать исключение или нет, если очистка ресурсов идет с ошибками. Тоже, ведь, на флагах работа построена.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[27]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: drol  
Дата: 07.08.08 13:44
Оценка: +1
Здравствуйте, CreatorCray, Вы писали:

D>>Не годится. Один-то уровень исключений из деструктора я ведь могу организовать. А там всё точно так же: недобитый объект, все дела... Однако не мешает

D>>Я всё-таки полагаю, что смотреть надо в сторону стека и расположения объектов на нём. В особенности собственно исключения и локальных объектов создаваемых/уничтожаемых вызываемыми при раскрутке деструкторами.
CC>Вопрос в том, что вот покинул объект область видимости и сработал его деструктор. А в деструкторе на полдороги вылетело исключение и некоторые нужные шаги в деструкторе не выполнились. Ты это исключение где то выше поймал и как то обработал. Как теперь "додеструктить" объект то?

Ниже в точности Ваш пример. Всё замечательно ловится и успешно доходит до "return 0;" безо всяких terminate()
И при этом объект a не менее успешно "недодеструкчен"...

#include <exception>
#include <iostream>

using namespace std;

class A {
public:
    ~A() {
        cout<<"~A() (before throw)"<<endl;
        throw exception();
        cout<<"~A() (after throw)"<<endl;
    }
};

int main(int, char**) {
    try {
        A a;
    } catch(...) {
        cout<<"exception catched"<<endl;
    }

    cout<<"OK => return 0"<<endl;

    return 0;
}


*Читайте стандарт, он рулез
Re[28]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: CreatorCray  
Дата: 07.08.08 14:01
Оценка:
Здравствуйте, drol, Вы писали:

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


D>>>Не годится. Один-то уровень исключений из деструктора я ведь могу организовать. А там всё точно так же: недобитый объект, все дела... Однако не мешает

D>>>Я всё-таки полагаю, что смотреть надо в сторону стека и расположения объектов на нём. В особенности собственно исключения и локальных объектов создаваемых/уничтожаемых вызываемыми при раскрутке деструкторами.
CC>>Вопрос в том, что вот покинул объект область видимости и сработал его деструктор. А в деструкторе на полдороги вылетело исключение и некоторые нужные шаги в деструкторе не выполнились. Ты это исключение где то выше поймал и как то обработал. Как теперь "додеструктить" объект то?

D>Ниже в точности Ваш пример. Всё замечательно ловится и успешно доходит до "return 0;" безо всяких terminate()

D>И при этом объект a не менее успешно "недодеструкчен"...

Третий раз повторяю: И как его корректно додеструктить после этого? Объект покинул зону видимости и не доступен. Получается что исключение выброшенное из деструктора не может гарантировать правильную раскрутку стека.

+ попробуй вот этот вариант:
#include <exception>
#include <iostream>

using namespace std;

class A {
public:
    A(int v)    {m_v = v; cout << "A(" << v << ");\n";}
    ~A() {
        cout<<"~A(" << m_v <<") (before throw)"<<endl;
        throw exception();
        cout<<"~A(" << m_v <<") (after throw)"<<endl;
    }

    int m_v;
};

int main(int, char**) {
    try {
        A a(1),b(2);
    } catch(...) {
        cout<<"exception catched"<<endl;
    }

    cout<<"OK => return 0"<<endl;

    return 0;
}


у меня он приводит к крэшу приложения при повторном исключении.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Re[29]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: drol  
Дата: 07.08.08 14:14
Оценка:
Здравствуйте, CreatorCray, Вы писали:

CC>Третий раз повторяю: И как его корректно додеструктить после этого? Объект покинул зону видимости и не доступен.


Никак. Однако, как Вы могли убедиться на моём примере, с точки зрения C++, программе это не мешает.

CC>Получается что исключение выброшенное из деструктора не может гарантировать правильную раскрутку стека.


"Правильная раскрутка" это то что допускает стандарт. Мой пример он допускает, и значит проблема не в "недодеструкченности".

CC>+ попробуй вот этот вариант:

CC>у меня он приводит к крэшу приложения при повторном исключении.

Конечно приводит, бо у Вас там два объекта. При выходе из блока вызывается деструктор для b. В нём происходит исключение. Стартует раскрутка стека. Она вызывает деструктор a. И в нём тоже происходит исключение. Только на сей раз это исключение при раскрутке стека, и строго согласно стандарту следует terminate()

Если в Вашем примере оставить только один объект — всё будет нормально. То бишь "недодеструкченный" объект + продолжающая работать как ни в чём не бывало программа.
Re[17]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: IB Австрия http://rsdn.ru
Дата: 07.08.08 15:35
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>Неверно. Повторный выброс исключения в C#/Java затирает предидущее исключение.

Не всегда. Справедливости ради, надо заметить, что есть и InnerException и просто throw без параметров, что в том или ином виде делает доступным оригинальное исключение выше по стеку.
... << RSDN@Home 1.2.0 alpha rev. 673>>
Мы уже победили, просто это еще не так заметно...
Re[18]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: nikov США http://www.linkedin.com/in/nikov
Дата: 07.08.08 16:18
Оценка: +1
Здравствуйте, IB, Вы писали:

C>>Неверно. Повторный выброс исключения в C#/Java затирает предидущее исключение.

IB>Не всегда. Справедливости ради, надо заметить, что есть и InnerException и просто throw без параметров, что в том или ином виде делает доступным оригинальное исключение выше по стеку.

Покажи код, если можно.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.