Re[15]: Re[2]: Зачем надо throw new CMyException
От: Ведмедь Россия  
Дата: 12.03.03 13:06
Оценка:
Здравствуйте, Borisman, Вы писали:

B>То, что для одного ошибка — для другого — проза жизни . Это смотря с какой стороны посмотреть. Я лишь говорю о том, что нет единого правила, говорящего о том, следует применять обработку исключений или нет. Но является ли неправильный пароль ИСКЛЮЧИТЕЛЬНОЙ ситуацией? Сколько раз из ста пользователь ошибается при наборе пароля?


Согласен с тем, что точных правил нет, но и не пользоваться возможностями try/catch, когда они очень хорошо ложаться как то тоже не хорошо

B>Не следует использовать средства языка только потому, что они есть. Если нет смысла в применении половины С++ — значит, так тому и быть. Когда Вы в последний раз применяли оператор , (запятая) ?


Вчерась Вообще если циклы сложные, то он часто удобен бывает
Да пребудет с тобой Великий Джа
Re[6]: Зачем надо throw new CMyException
От: trial  
Дата: 12.03.03 13:17
Оценка:
ME>Выбрасывается всегда копия.

ME>
ME>class EEE
ME>{
ME>private:
ME>    EEE(const EEE&); // закоментировать, чтобы откомпилилось
ME>};

ME>



Требование конструктора копий и выброс копии — это всё таки разные вещи

следующий код напечатает на экране 10


class CEx
{
public:
    int m_i;

    CEx( const CEx& e )
    {
        __asm
        {
            int 3;
        }
    }

    CEx( int i ) 
    {
        m_i = i;
    };
    
};
int main(int argc, char* argv[])
{
    try
    {
        throw CEx( 10 );
    }
    catch( CEx& e )
    {
        printf( "%d", e.m_i );
    }
    return 0;
}


Хотя если бы создавалась копия был бы DebugBreak

Но если сделать CEx( const CEx& e ) приватным действительно перестанет компилиться...
Кажеться где-то в стандарте это есть...но не помню где

Надо что бы гуру напомнили
Re[7]: Зачем надо throw new CMyException
От: trial  
Дата: 12.03.03 13:30
Оценка:
Вот, вспомнил!

Вот так конструктор копий вызывается

CEx ex( 10 );
throw ex;


а вот так — нет

throw CEx( 10 );


и стандарт это разрешает (пункт не помню)
Re[5]: Зачем надо throw new CMyException
От: Lostar Россия  
Дата: 12.03.03 14:02
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>Здравствуйте, Borisman.


А>Хотелось бы отметить, что у передачи объекта-исключения указателем есть и определенные преимущества (не умаляя недостатков ).


А>Например, при передаче значением выполнить что-то вроде InnerException в .Net (т. е. обернуть одно исключение другим, так что исходное исключение становится причиной исключения на более высоком уровне абстракции) можно, но становится некрасиво.


Мои 5 копеек не в пользу исключений бросаемых по указателю:
Если исключение пересекает границы модулей то непонятно как его надо удалять(либо накладывать жесткие ограничения линковку CRT к модулям).
... << RSDN@Home 1.0 beta 6a >>
С уважением, Николай.
Re[3]: Re: Зачем надо throw new CMyException
От: sev http://www.demoforge.com
Дата: 12.03.03 14:34
Оценка:
sev>>А ниже показано, как это решение работает "в жизни".
sev>>void ThrowingFunc()
sev>>{
sev>>throw CSystemExceptionPtr(new CSystemException(E_FAIL));
sev>>}
sev>>Самое главное, что код абсолютно безопасен (я так думаю во всяком случае
sev>>
> А я не понял, а что будет если при вызове ThrowingFunc new выкинет скажем
> std::bad_alloc? Все-таки не нравится мне эта идея с динамическим выделением
> памяти при генерации исключения.

Ну как что будет, полетит std::bad_alloc, вестимо
Только чем это плохо?

> Проще надо ИМХО, конечно.


Предлагайте варианты...

С уважением,
Евгений Суходолин
http://www.demoforge.com/
Posted via RSDN NNTP Server 1.4.6 beta
Re[3]: Re: Зачем надо throw new CMyException
От: sev http://www.demoforge.com
Дата: 12.03.03 14:34
Оценка:
[...skipped...]
> При этом, конечно, придется делать такой typedef для inherited (базового
> исключения) в определении исключения, но тогда можно избавиться от того
> "typedef'а в минусах".

В точности так я и сделал сначала
Но это замена одного минуса на другой: нужно не забывать делать этот самый
typedef внутри каждого нового класса. Причём, если забыть, то всё будет
"работать".
А вот если нынешний typedef забыть, то станет невозможно написать
соответствующий catch

Да, кстати, тогда придётся в catch писать вот такие монструозные конструкции:

catch (CExceptionPtrT<СSystemException>& e)
{ ... }

В общем, поэтому я и отказался от typedef внутри класса.

С уважением,
Евгений Суходолин
http://www.demoforge.com/
Posted via RSDN NNTP Server 1.4.6 beta
Re[4]: Re: Зачем надо throw new CMyException
От: grs Россия  
Дата: 12.03.03 15:09
Оценка:
Здравствуйте, sev, Вы писали:

sev>Ну как что будет, полетит std::bad_alloc, вестимо

sev>Только чем это плохо?

Например тем, что ловить ты будешь СExceptionPtr (тем более, что в заголовочном файле у тебя уже есть COutOfMemoryExeption). А выкинется std::bad_alloc (особенно в случае COutOfMemoryExeption), которая останется неперехваченной. Или я чего-то не понял?

>> Проще надо ИМХО, конечно.


sev>Предлагайте варианты...


Ну мне такая штука была нужна, просто для записи более подробной отладочной информации о том, что же сбойнуло. Ну так каждое исключение на своем уровне просто писало в лог, то что знало и все — дальше новое throw, если нужно, и перехват в верху . Мне было вполне достаточно. А если речь идет о клиенте, а не о серваке, то юзеру вполне достаточно сказать "облом тебе", а не пугать кучей непонятной информации. Так что получалось дешего и сердито. Просто для того, чтобы что-то предлагать надо бы выснянить, я для чего конкретно такой огород городим.

sev>С уважением,

sev>Евгений Суходолин
sev>http://www.demoforge.com/
Re[5]: Re: Зачем надо throw new CMyException
От: sev http://www.demoforge.com
Дата: 12.03.03 15:25
Оценка:
sev>>Ну как что будет, полетит std::bad_alloc, вестимо
sev>>Только чем это плохо?
> Например тем, что ловить ты будешь СExceptionPtr (тем более, что в
> заголовочном файле у тебя уже есть COutOfMemoryExeption).

COutOfMemoryExeption был дан скорее для примера, не нужно
рассматривать его как замену std::bad_alloc, он для этого не задумывался

> А выкинется std::bad_alloc (особенно в случае COutOfMemoryExeption), которая

> останется неперехваченной. Или я чего-то не понял?

std::bad_alloc останется неперехваченным тем кодом, который ожидал
увидеть потомка CException. Что вполне логично. Разумеется, что где-то
в программе должен быть и обработчик std::bad_alloc А также всех прочих,
порождённых от std::exception. Т.е. я не претендую на замену std::exception
своими исключениями. Мои исключения _логические_, в то время как
std::bad_alloc сугубо системное.

Как вариант, все не-CException могут ловиться через catch(...) и транслироваться
в CException-derived исключения. Ссыка на оригинальный способ это сделать
здесь уже пробегала.

>>> Проще надо ИМХО, конечно.

sev>>Предлагайте варианты...
> Ну мне такая штука была нужна, просто для записи более подробной отладочной
> информации о том, что же сбойнуло. Ну так каждое исключение на своем уровне
> просто писало в лог, то что знало и все — дальше новое throw, если нужно, и
> перехват в верху . Мне было вполне достаточно. А если речь идет о клиенте, а
> не о серваке, то юзеру вполне достаточно сказать "облом тебе", а не пугать
> кучей непонятной информации. Так что получалось дешего и сердито. Просто для
> того, чтобы что-то предлагать надо бы выснянить, я для чего конкретно такой
> огород городим.

Тут могут быть разные идеи, но я исходил из того, что _мне нужно_ иметь
список вложенных исключений a-la .NET. Я не вижу достойной альтернативы
сделать это без использования динамической памяти.

С уважением,
Евгений Суходолин
http://www.demoforge.com/
Posted via RSDN NNTP Server 1.4.6 beta
Re[15]: Re[2]: Зачем надо throw new CMyException
От: Areex  
Дата: 12.03.03 21:24
Оценка:
Здравствуйте, Borisman, Вы писали:

A>>Нет, ошибка это ошибка. Функция же может только вернуть результат, который можно трактовать как ошибку.


B>То, что для одного ошибка — для другого — проза жизни . Это смотря с какой стороны посмотреть. Я лишь говорю о том, что нет единого правила, говорящего о том, следует применять обработку исключений или нет. Но является ли неправильный пароль ИСКЛЮЧИТЕЛЬНОЙ ситуацией? Сколько раз из ста пользователь ошибается при наборе пароля?


Эээ... ты случайно исключение (как особая ситуация) и исключительно редко не путаешь?
Вполне себе исключительная. Как пример: запросил пароль, пробуем расшифровать + исключение в случае неудачи.
Чем тут плохо исключение? Ресурсов больше надо? Да явных проверок будет не меньше. Да и куда тут торопится, как можно быстрее еще раз пароль спросить?
К тому же исключения вводят единообразие в обработке ошибок, что кстати очень полезно. И чем больше проект, тем полезнее.

B>Не следует использовать средства языка только потому, что они есть. Если нет смысла в применении половины С++ — значит, так тому и быть. Когда Вы в последний раз применяли оператор , (запятая) ?


Хм... А ты функции только с одним аргументом используешь?
"Do you realize what you just did?"
Re[16]: Re[2]: Зачем надо throw new CMyException
От: Михаил Можаев Россия www.mozhay.chat.ru
Дата: 13.03.03 10:21
Оценка:
Здравствуйте, Areex, Вы писали:

B>>Не следует использовать средства языка только потому, что они есть. Если нет смысла в применении половины С++ — значит, так тому и быть. Когда Вы в последний раз применяли оператор , (запятая) ?

A>Хм... А ты функции только с одним аргументом используешь?

Запятая в списке параметров ф-ции — это не "оператор ,".
Вот если сделать так:
f((x, y, z));

то здесь будет "оператор ,", но и смысл у выражения будет абсолютно другой (ф-ция с одним аргументом).
... << RSDN@Home 1.0 beta 5 >>
Re[2]: Зачем надо throw new CMyException
От: Михаил Можаев Россия www.mozhay.chat.ru
Дата: 13.03.03 10:21
Оценка:
Здравствуйте, GvozdodeR, Вы писали:

B>>1) throw CMyException(...)

B>>2) throw new CMyException(...)
GR>В пользу второго способа, imho, есть только один разумный довод (производительность я не считаю, ибо ей с исключениями не по пути), с которым я буквально сегодня столкнулся. Если исключение выбрасывается с помощью способа №1 из .dll, а ловится, к примеру, в .exe, причем при раскрутке стека та самая .dll выгружается, то произойдет Access Violation в catch-блоке.

Хм... Интересно. Можно поподробнее?
... << RSDN@Home 1.0 beta 5 >>
Re[2]: Зачем надо throw new CMyException
От: Павел Кузнецов  
Дата: 13.03.03 16:35
Оценка:
Здравствуйте, GvozdodeR, Вы писали:

B>> 1) throw CMyException(...)

B>> 2) throw new CMyException(...)

G> Если исключение выбрасывается с помощью способа №1 из .dll, а ловится,

G> к примеру, в .exe, причем при раскрутке стека та самая .dll выгружается,
G> то произойдет Access Violation в catch-блоке.

А при способе (2) этот же Access Violation произойдет в момент delete,
если класс CMyException определен в выгруженной DLL. Что наталкивает
на мысли, что выгружать DLL в этот момент -- не самая хорошая мысль
Posted via RSDN NNTP Server 1.4.6 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[3]: Зачем надо throw new CMyException
От: GvozdodeR  
Дата: 13.03.03 21:12
Оценка:
Здравствуйте, Павел Кузнецов, Вы писали:

ПК>А при способе (2) этот же Access Violation произойдет в момент delete,

ПК>если класс CMyException определен в выгруженной DLL. Что наталкивает
ПК>на мысли, что выгружать DLL в этот момент -- не самая хорошая мысль

Но только если класс CMyException определен в той самой .dll!!!

При необходимости выгрузки .dll в деструкторе, в случае раскрутки стека выбросом исключения, можно отложить выгрузку .dll на atexit. С другой стороны, если исключение фатально, то зачем удалять экземпляр объекта-исключения, ведь защищенная ОС сама вычистит память после завершения приложения. И еще: если, допустим, наш CMyException наследован от std::exception, то в нем, вероятно, переопределен метод what(), тогда выгружать .dll вообще невозможно, т. к. вместе с ней выгрузится и код метода what().

В общем, случаи разные бывают...
Re: Зачем надо throw new CMyException
От: alexkro  
Дата: 15.03.03 11:24
Оценка:
Здравствуйте, Borisman, Вы писали:

B>На вопрос, как нужно выбрасывать исключения, есть два мнения:

B>1) throw CMyException(...)
B>2) throw new CMyException(...)

Если пишется MFC приложение и CMyException унаследован от CException, то лучше следовать второму методу, потому что в MFC так делается сплошь и рядом. Тогда один catch блок типа:

catch( Exception * e ) { ... e->Delete(); }


будет работать и для твоих и для MFC исключений.

Почему так сделано в MFC — это уже другой вопрос. Вероятно, по историческим причинам.
Re: Зачем надо throw new CMyException
От: ch00k  
Дата: 16.03.03 16:33
Оценка:
Здравствуйте, Borisman, Вы писали:

B>На вопрос, как нужно выбрасывать исключения, есть два мнения:

B>1) throw CMyException(...)
B>2) throw new CMyException(...)

B>

B>И то и то работает. Но во втоом случае приходится явно удалять экземпляр исключения в секции catch:

B>try {

B> ...
B> throw new CMyException(...);
B>} catch(CMyException *exc)
B>{
B> ...
B> delete exc; // Ну или там в большинстве случаев — exc->Delete(), которая вызывает delete this;
B>}

С точки зрения удобства и надёжности, лучше не использовать new. Но в этом случае нужно помнить что
в catch нужно ловить не CMyException ex, а CMyException & ex (а лучше вообще const CMyException & ex), в противном случае каждый раз будет вызываться конструктор копирования, что может в лучшем случае вызвать замедление работы, а в худшем (если конструктор копирования не описан, а нужен) вообще может привести к краху программы.

Что жа до передачи указателя, то это, на мой взгляд, слишком большой геморрой с потенциальной возможностью налететь потом на memory leaks
Re[8]: Зачем надо throw new CMyException
От: The Lex Украина  
Дата: 18.03.03 21:12
Оценка:
Здравствуйте, trial, Вы писали:

T>Вот, вспомнил!


T>Вот так конструктор копий вызывается

T>
T>CEx ex( 10 );
T>throw ex;
T>

T>а вот так — нет
T>
T>throw CEx( 10 );
T>

T>и стандарт это разрешает (пункт не помню)

Так ведь второй случай — это не констуктор копирования
CEx(const CEx& )
а просто конструктор
CEx(int )

учите матчасть...
Голь на выдумку хитра, однако...
Re[15]: Re[2]: Зачем надо throw new CMyException
От: The Lex Украина  
Дата: 18.03.03 21:15
Оценка:
Здравствуйте, Borisman, Вы писали:

A>>Нет, ошибка это ошибка. Функция же может только вернуть результат, который можно трактовать как ошибку.


B>То, что для одного ошибка — для другого — проза жизни . Это смотря с какой стороны посмотреть.


Ошибка — проза жизни разве что для неудачника...

B>Я лишь говорю о том, что нет единого правила, говорящего о том, следует применять обработку исключений или нет. Но является ли неправильный пароль ИСКЛЮЧИТЕЛЬНОЙ ситуацией? Сколько раз из ста пользователь ошибается при наборе пароля?


Если применять, то уже применять — нет, так не применять вообще. ИМХО

A>>Ты не аргументировал, почему не следует. Обработка ошибок прямое назначение исключений. Этак половину c++ можно не использовать, мало ли у кого какой здравый смысл.


B>Не следует использовать средства языка только потому, что они есть. Если нет смысла в применении половины С++ — значит, так тому и быть. Когда Вы в последний раз применяли оператор , (запятая) ?


Да, не следует. Но применять разные средства обработки подобных ситуаций еще более не следует.
for (i = 0, j = 0; i < first && j < second; i++, j++)
{
  cout << i << " -> " << j << endl;
}

А вообще-то "," в циклах очень часто встречается в сложных итераторах...
Голь на выдумку хитра, однако...
Re[9]: Зачем надо throw new CMyException
От: Михаил Можаев Россия www.mozhay.chat.ru
Дата: 19.03.03 09:38
Оценка: 5 (1)
Здравствуйте, The Lex, Вы писали:

T>>Вот так конструктор копий вызывается

T>>
T>>CEx ex( 10 );
T>>throw ex;
T>>

T>>а вот так — нет
T>>
T>>throw CEx( 10 );
T>>

T>>и стандарт это разрешает (пункт не помню)

Пункт 15.3/18 (приведен ниже)

TL> Так ведь второй случай — это не констуктор копирования

TL>
TL>CEx(const CEx& )
TL>
а просто конструктор

TL>
TL>CEx(int )
TL>

TL> учите матчасть...

То, что это — не конструктор копирования — верно. Но верно так же и то, что вслед за вызовом этого конструктором вполне может последовать вызов конструктора копирования для создания копии выбрасываемого объекта:

15.1/3A throw-expression initializes a temporary object <...skip...>
The temporary is used to initialize the variable named in the matching handler (15.3).


Временный объект может создаваться или не создаваться. И конструктор копирования может либо вызываться, либо не вызываться соответственно:

15.3/18If the use of a temporary object can be eliminated without changing the meaning of the program except for
execution of constructors and destructors associated with the use of the temporary object, then the optional
name can be bound directly to the temporary object specified in a throw-expression causing the handler to
be executed. The copy constructor and destructor associated with the object shall be accessible even when
the temporary object is eliminated.

... << RSDN@Home 1.0 beta 5 >>
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.