Re: Зачем надо throw new CMyException
От: Колян  
Дата: 11.03.03 12:28
Оценка: 18 (2)
Здравствуйте, Borisman, Вы писали:

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

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

Если ты будешь передавать исключение дальше, да еще, завернув его в другое, то, возможно, второй подход будет лучше. Но я так никогда не делаю. И вообще не понимаю, суть обсуждения производительности блоков try-catch. Кому интересно, насколько быстро моя программа может сбоить???

Никогда не используй try-catch для программирования логики. А если ты это сделал, то не ломай голову над производительностью программы. Одно другое исключает. Вот так.
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 >>
Re[4]: Зачем надо throw new CMyException
От: grs Россия  
Дата: 11.03.03 12:29
Оценка: -1
Здравствуйте, Borisman, Вы писали:


B>Вообще-то я довольно много где видал именно второй способ выброса исключений. В первый раз увидел его в здоровенном финансовом приложении HPR. Очень меня это сбило с панталыку — глупые программеры того проекта утверждали, что если выбрасывать стековый объект, то при раскрутке стека он того....удалится в общем.


Чем тяжелее бред, тем труднее на него реагировать...

А вообще, есть книжки Страуструпа (естественно) и Мейерса, где все расписано. Надо просто достать и прочитать внимательно. А резюме такое:
1) выбрасывается ТОЛЬКО стековый объет (НИ В КОЕМ СЛУЧАЕ НЕ УКАЗАТЕЛЬ)
2) перехватывается ССЫЛКА (не значение!).
Зачем надо throw new CMyException
От: Borisman  
Дата: 11.03.03 08:11
Оценка:
На вопрос, как нужно выбрасывать исключения, есть два мнения:
1) throw CMyException(...)
2) throw new CMyException(...)


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

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

Второй подход вроде как хуже из-за дополнительной необходимости удалять исключение. Или это фича?

Бойцы, у кого какое мнение?
Re: Зачем надо throw new CMyException
От: Геннадий Васильев Россия http://www.livejournal.com/users/gesha_x
Дата: 11.03.03 10:26
Оценка:
Здравствуйте, Borisman, Вы писали:

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

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

B>

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

Угу. Первый чуть медленнее, поскольку выброшенный CMyException будет неявно копироваться при передаче из try-блока в catch.
Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
P.S.: Винодельческие провинции — это есть рулез!
Re[2]: Зачем надо throw new CMyException
От: Ведмедь Россия  
Дата: 11.03.03 10:44
Оценка:
Здравствуйте, Геннадий Васильев, Вы писали:

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


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

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

B>>

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

ГВ>Угу. Первый чуть медленнее, поскольку выброшенный CMyException будет неявно копироваться при передаче из try-блока в catch.


Не знаю, не проверял, но при втором много потенциальных взможностьей упустить память — пример



try
{
throw new CMyException();
}catch(...)
{
//попасть мы сюда попали, а память освобождать как?
}


Пример несколько надуман, но если нижележащий код кидает в try указатель, а ты об этом не знаешь, то найти этот лик в памяти будет очень проблематично.
Да пребудет с тобой Великий Джа
Re[2]: Зачем надо throw new CMyException
От: grs Россия  
Дата: 11.03.03 10:47
Оценка:
Здравствуйте, Геннадий Васильев, Вы писали:

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


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

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

B>>

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

ГВ>Угу. Первый чуть медленнее, поскольку выброшенный CMyException будет неявно копироваться при передаче из try-блока в catch.


Это если напишешь catch(CMyExeption). А ты так не пиши, ты пиши catch(CMyExeption&) как все нормальные люди.

Вообще первый способ (с new) не просто кривой, а очень кривой. Во первых, почти гарантирована утечка памяти — кто-нибудь либо не поймает, либо не удалит. Например в случае, если исключение попадает в блок catch(...) откуда ты узнаешь, что нужно сделать delete CMyExeption.
Во вторых, страдает столь любимая всеми нами производительность. Операция new — вещь в этом смысле очень дорогая...
Re[2]: Зачем надо throw new CMyException
От: Геннадий Васильев Россия http://www.livejournal.com/users/gesha_x
Дата: 11.03.03 10:52
Оценка:
Здравствуйте, Borisman, Вы писали:

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

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

B>>

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

ГВ>Угу. Первый чуть медленнее, поскольку выброшенный CMyException будет неявно копироваться при передаче из try-блока в catch.


Строго говоря, первый способ медленнее на передаче. Второй способ заторомозит при создании объекта-исключения, чем скорее всего сожрёт все "выигрыши". (псхпп grs)
Кстати, второй способ менее безопасен, поскольку new сама по себе может стать источником исключений.
Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
P.S.: Винодельческие провинции — это есть рулез!
Re[3]: Зачем надо throw new CMyException
От: Borisman  
Дата: 11.03.03 12:00
Оценка:
Здравствуйте, grs, Вы писали:

grs>Это если напишешь catch(CMyExeption). А ты так не пиши, ты пиши catch(CMyExeption&) как все нормальные люди.


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

Вот только одна закавыка: я толком не знаю, как раскручивается стек при ислючении, но тут разница между двумя подходами в том, где именно лежит все исключение-объект. В первом случае в стэке лежит он весь, а во втором — только указатель. Интересно, что проще для компилятора — раскрутить стек так, чтоб доступен был указатель (4 байта) или весь объект (много байтов).

Вообще-то я довольно много где видал именно второй способ выброса исключений. В первый раз увидел его в здоровенном финансовом приложении HPR. Очень меня это сбило с панталыку — глупые программеры того проекта утверждали, что если выбрасывать стековый объект, то при раскрутке стека он того....удалится в общем. Но потом, хорошенько подумав, я решил, что вроде-как не должен. Ведь делаем же мы вещи типа throw "приветик!" — и ниче...все корректно...

Еще есть подозрение, что просто не все компиляторы одинаково исключения обрабатывают (вспомним, что в старых версиях компиляторов С++ они вообще не везде были) и где-то как-то по разному работает выбрасывание стековых объектов. А вот динамические объекты типа работают....
Re[4]: Зачем надо throw new CMyException
От: Аноним  
Дата: 11.03.03 12:32
Оценка:
Здравствуйте, Borisman.

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

Например, при передаче значением выполнить что-то вроде InnerException в .Net (т. е. обернуть одно исключение другим, так что исходное исключение становится причиной исключения на более высоком уровне абстракции) можно, но становится некрасиво.
Re[2]: Re[2]: Зачем надо throw new CMyException
От: Areex  
Дата: 11.03.03 15:56
Оценка:
Здравствуйте, Колян, Вы писали:

К>Никогда не используй try-catch для программирования логики.


Это почему?
"Don't worry! The chances of me blowing a climb walls roll twice, at my level, are infinintesimal."
Re[3]: Re[2]: Зачем надо throw new CMyException
От: Ведмедь Россия  
Дата: 11.03.03 16:28
Оценка:
Здравствуйте, Areex, Вы писали:

A>Здравствуйте, Колян, Вы писали:


К>>Никогда не используй try-catch для программирования логики.


A>Это почему?


A>


Видимо имелос ввиде то что try/catch вызывает некоторый провал в производительности.
Да пребудет с тобой Великий Джа
Re[4]: Re[2]: Зачем надо throw new CMyException
От: Аноним  
Дата: 11.03.03 16:30
Оценка:
Здравствуйте, Ведмедь, Вы писали:

В>Видимо имелос ввиде то что try/catch вызывает некоторый провал в производительности.


... и, что еще более важно, в прозрачности и сопровождаемости кода.
Re[5]: Re[2]: Зачем надо throw new CMyException
От: Ведмедь Россия  
Дата: 11.03.03 16:33
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, Ведмедь, Вы писали:


В>>Видимо имелос ввиде то что try/catch вызывает некоторый провал в производительности.


А>... и, что еще более важно, в прозрачности и сопровождаемости кода.


Ну не всегда. в некоторых случаях IMHO прозрачней как раз через try/catch ( например, выход из N вложенных циклов )
Да пребудет с тобой Великий Джа
Re[2]: Зачем надо throw new CMyException
От: Ведмедь Россия  
Дата: 11.03.03 16:39
Оценка:
Здравствуйте, Колян, Вы писали:


К>Если ты будешь передавать исключение дальше, да еще, завернув его в другое, то, возможно, второй подход будет лучше. Но я так никогда не делаю. И вообще не понимаю, суть обсуждения производительности блоков try-catch. Кому интересно, насколько быстро моя программа может сбоить???


Кстати не совсем верно. В данном вопросе да, производительность значения не имеет. Я тоже считаю, что если произошло исключение, то обработать его в 90 процентов случае время есть и можно уже не торопиться Но факт в том что try/catch не в лучшей сторону влияет на производительность, не зависимо от того, происходит или нет исключение. А вот это не приятно.
Да пребудет с тобой Великий Джа
Re[6]: Re[2]: Зачем надо throw new CMyException
От: Аноним  
Дата: 11.03.03 16:41
Оценка:
Здравствуйте, Ведмедь, Вы писали:

В>>>Видимо имелос ввиде то что try/catch вызывает некоторый провал в производительности.


А>>... и, что еще более важно, в прозрачности и сопровождаемости кода.


В>Ну не всегда. в некоторых случаях IMHO прозрачней как раз через try/catch ( например, выход из N вложенных циклов )


Вы будете смеяться, но goto еще никто не отменял. А избежание goto — не самоцель.
Re[7]: Re[2]: Зачем надо throw new CMyException
От: Ведмедь Россия  
Дата: 11.03.03 16:46
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, Ведмедь, Вы писали:



А>Вы будете смеяться, но goto еще никто не отменял. А избежание goto — не самоцель.


goto не сделаешь из вложенной функции, кроме того в зависимости от типа кидаемого исклюения обработка может происходить в разных местах.
пример —


void CheckSome( int a )
{
  if( a = 0 )
    throw (int)1;//завершили
}


void SomeFunc()
{
try
{
 for(...)
  ...
   for(..)
  {
    CheckSome( a );
  }
}catch( int i )
{
   printf( "some var = %d", i );
}
}
Да пребудет с тобой Великий Джа
Re[8]: Re[2]: Зачем надо throw new CMyException
От: Аноним  
Дата: 11.03.03 17:10
Оценка:
Здравствуйте, Ведмедь, Вы писали:

В>goto не сделаешь из вложенной функции, кроме того в зависимости от типа кидаемого исклюения обработка может происходить в разных местах.

В>пример —

В>
В>void CheckSome( int a )
В>{
В>  if( a = 0 )
В>    throw (int)1;//завершили
В>}

В>void SomeFunc()
В>{
В>try
В>{
В> for(...)
В>  ...
В>   for(..)
В>  {
В>    CheckSome( a );
В>  }
В>}catch( int i )
В>{
В>   printf( "some var = %d", i );
В>}
В>}
В>


Ой, какой бандитизм! Ничего не ясно.

Может, так?

bool CheckSome( int a )
{
  return a = 0;
}

void SomeFunc()
{
 for(...)
  ...
   for(..)
  {
    if (CheckSome( a )) goto found;
  }
found:
   printf( "some var = %d", i );
}


Вот это я понимаю!
Re[9]: Re[2]: Зачем надо throw new CMyException
От: Ведмедь Россия  
Дата: 11.03.03 17:26
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Ой, какой бандитизм! Ничего не ясно.


А>Может, так?


А>
А>bool CheckSome( int a )
А>{
А>  return a = 0;
А>}

А>void SomeFunc()
А>{
А> for(...)
А>  ...
А>   for(..)
А>  {
А>    if (CheckSome( a )) goto found;
А>  }
А>found:
А>   printf( "some var = %d", i );
А>}
А>


А>Вот это я понимаю!


а если так

void InnerCheck2( a )
{
  if( a == 1 )
     throw "oooops";
  throw L"OOOOPS";
}

void InnerCheck1( a )
{
   InnerCheck2(a);
   throw (int)a;
}

void SomeCheck( a )
{
     InnerCheck1(a);
}


void SomeFunction
{
  try
  {
    for()
      ...
     for()
    {
            SomeCheck( a );
    }
  }catch( int e )
  {
    printf( "some var1 = %d", i );
  }catch( char* e )
  {
    printf( " some var2 = %s",e );
  }
  catch( wchar_t* e )
  {
     printf( " some var2 = %s",e );
     throw e;// перекинули на обработку дальше
  }
  printf( "final" );
}



НА мой взгляд прозрачно. С goto так получится? И сколько их тут будет?
Да пребудет с тобой Великий Джа
Re[5]: Зачем надо throw new CMyException
От: MaximE Великобритания  
Дата: 11.03.03 17:59
Оценка:
Здравствуйте, grs, Вы писали:

он того....удалится в общем.

grs>Чем тяжелее бред, тем труднее на него реагировать...


grs>А вообще, есть книжки Страуструпа (естественно) и Мейерса, где все расписано. Надо просто достать и прочитать внимательно. А резюме такое:

grs>1) выбрасывается ТОЛЬКО стековый объет (НИ В КОЕМ СЛУЧАЕ НЕ УКАЗАТЕЛЬ)

Выбрасывается всегда копия.

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

void f()
{
    throw EEE();
}

int _tmain(int argc, _TCHAR* argv[])
{
    f();
    return 0;
}



grs>2) перехватывается ССЫЛКА (не значение!).


только если использовать синтаксис по ссылке (catch(some&)).
Re: Re: Зачем надо throw new CMyException
От: sev http://www.demoforge.com
Дата: 11.03.03 19:44
Оценка:
Приветствую!

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

> 1) throw CMyException(...)
> 2) throw new CMyException(...)
[...skipped...]
> Второй подход вроде как хуже из-за дополнительной необходимости удалять
> исключение. Или это фича?
> Бойцы, у кого какое мнение?

Замечательный вопрос. Я буквально на днях всерьёз озаботился этой проблемой.
После некоторых раздумий я реализовал решение, коим весьма теперь доволен.
Все проблемы с автоматическим удалением исключения в нём решены, а также
добавлена возможность "вложенности" исключений в стиле .NET.

Решение можно посмотреть в исходном тексте вот здесь:
http://www.demoforge.com/misc/SmartExceptions.h

А ниже показано, как это решение работает "в жизни".

void ThrowingFunc()
{
throw CSystemExceptionPtr(new CSystemException(E_FAIL));
}

void LibraryFunc()
{
try
{
ThrowingFunc();
}
catch (CExceptionPtr& e)
{
throw CLibraryExceptionPtr(new CLibraryException("Algorithm
failed.",e));
}
}

void UserFunc()
{
try
{
LibraryFunc();
}
catch (CExceptionPtr& e)
{
CException* pe = e.get();
while (pe)
{
printf("%s", pe->GetMessage()); // выводим стек ошибок
pe = pe->GetInnerException();
}
}
}

Самое главное, что код абсолютно безопасен (я так думаю во всяком случае
в плане возможных утечек памяти. Т.е. не напрягаясь делаем new, и не вспоминаем
о delete Что принципиально отличает это решение от того, что есть в MFC.
Также мы можем свободно передавать исключения из потока в поток, т.е. для этого
их не нужно клонировать

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

Любые усовершенствования приветствуются

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

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

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

B>Бойцы, у кого какое мнение?


В пользу второго способа, imho, есть только один разумный довод (производительность я не считаю, ибо ей с исключениями не по пути), с которым я буквально сегодня столкнулся. Если исключение выбрасывается с помощью способа №1 из .dll, а ловится, к примеру, в .exe, причем при раскрутке стека та самая .dll выгружается, то произойдет Access Violation в catch-блоке. В таком случае, лучший вариант -- выбросить указатель на исключение, а не экземпляр. Я обошел эту ситуацию, обернув код выгрузки .dll условием if(!std::uncaught_exception())

Огромный плюс в первом способе выброса исключения в том, что так ведет себя стандартная библиотека. Поэтому, если придется использовать вариант №2, то возникнут проблемы с отловом ее исключений, а также многих других библиотек (boost, например)
Re[5]: Зачем надо throw new CMyException
От: Borisman  
Дата: 12.03.03 05:43
Оценка:
Здравствуйте, Аноним, Вы писали:

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


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


Когда я впервый прочитал и понял, зачем в .NET нужен InnerException, я задумался, как же я всю жизнь обходился ьез InnerEcxeption. Вообще всю эту микробучу на форуме я затеял потому, что сейчас пытаюсь придумать свою библиотеку исключений под С++ где была бы поддержка InnerException. Есть по сути два варианта:
1) Либо бросать указатели на динамически создаваемые исключения и иметь затем проблемы с их удалением (зато быстро работает).
2) Либо бросать копии исключений и обертывать их другими исключениями и иметь проблемы сос скоростью работы (зато никаких проблем с удалением исключений).

Лично мне второй вариант кажется предпочтительнее. Исключения на то и исключения, чтобы происходить сравнительно редко. Вообще обработка любого исключения — дело накладное и не особо тут выиграешь на кописровании классов.

Под влиянием общественности пришел в голову третий вариант — можно кидать объекты, ловить ссылки и вот эти ссылки(а не указатели) и оборачивать другими исключениями. Вот так надо и сделать, по-моему.
Re[2]: Зачем надо throw new CMyException
От: Borisman  
Дата: 12.03.03 05:46
Оценка:
К>Если ты будешь передавать исключение дальше, да еще, завернув его в другое, то, возможно, второй подход будет лучше. Но я так никогда не делаю. И вообще не понимаю, суть обсуждения производительности блоков try-catch. Кому

Согласен, см здесь http://www.rsdn.ru/forum/Message.aspx?mid=211994&amp;only=1
Автор: Borisman
Дата: 12.03.03
Re[10]: Re[2]: Зачем надо throw new CMyException
От: Borisman  
Дата: 12.03.03 06:00
Оценка:
Здравствуйте, Ведмедь, Вы писали:

В>а если так


В>
В>void InnerCheck2( a )
В>{
В>  if( a == 1 )
В>     throw "oooops";
В>  throw L"OOOOPS";
В>}

В>void InnerCheck1( a )
В>{
В>   InnerCheck2(a);
В>   throw (int)a;
В>}

В>void SomeCheck( a )
В>{
В>     InnerCheck1(a);
В>}

В>
В>void SomeFunction
В>{
В>  try
В>  {
В>    for()
В>      ...
В>     for()
В>    {
В>            SomeCheck( a );
В>    }
В>  }catch( int e )
В>  {
В>    printf( "some var1 = %d", i );
В>  }catch( char* e )
В>  {
В>    printf( " some var2 = %s",e );
В>  }
В>  catch( wchar_t* e )
В>  {
В>     printf( " some var2 = %s",e );
В>     throw e;// перекинули на обработку дальше
В>  }
В>  printf( "final" );
В>}
В>


Забавно. Но по-моему кидать что-то типа
 throw "Приветик из Австралии!"
весьма надуманно. Ну кому может понадобиться такой приветик? Кидают как правило что-нить вроде CArgumentException("IRQ_LEVEL", 0, 1) и в самых крайних случаях.

Я все это говорю к тому, что спор о том, что лучше — throw или goto достаточно бессмысленный. Исключения должны кидаться в ИСКЛЮЧИТЕЛЬНЫХ случаях, а не для выхода из каких-то там вложенных циклов. Если ситуация, когда нужно выйти из кучи вложеннных циклов (или там, функций) — достаточно типичная, пусть даже ошибочная, и часто происходящая, то не следует по-моему пользоваться исключениями. Выйдите как все нормальные люди выходят — через дверь (я имею в виду старый добрые операторы break, return и т.д. Насчет goto — я лично против. Вот уже 5 лет не написал ни одного оператора goto и прекрасно себя чуствую).

Типичный пример, который вычитан мной из МСДН.
Пользователь должен авторизироваться при коннекте к серверу. Можно, конечно, сделать так:

void Logon(const CString & name, const CString &passwd)
{
  ...
  if (!DB_HAS_ACCESS(name, passwd, currenttime, ...)) throw BadLogon();
}


Но концептуально это глупо. Ведь неверное набирание пароля — дело лостаточно обычное, чего тут за голову хвататься и исключениями кидаться.
Лучше все-таки по старинке:

void Logon(const CString & name, const CString &passwd)
{
  ...
  return DB_HAS_ACCESS(name, passwd, currenttime, ...);
}


Каждый инструмент должен использоваться по назначению.

Удалено избыточное цитирование. -- ПК.
Re[2]: Re: Зачем надо throw new CMyException
От: Borisman  
Дата: 12.03.03 06:12
Оценка:
sev>После некоторых раздумий я реализовал решение, коим весьма теперь доволен.
sev>Все проблемы с автоматическим удалением исключения в нём решены, а также
sev>добавлена возможность "вложенности" исключений в стиле .NET.

sev>Решение можно посмотреть в исходном тексте вот здесь:

sev>http://www.demoforge.com/misc/SmartExceptions.h

Да, действительно неплохо! Недостатка на самом деле два — второй — использование СException, a, значит, привязка к MFC. Но иначе все дела со снимком стека пришлось бы самому кодить. Очень, очень неплохо, мне понравилось. Именно что-то подобное я и хотел сам сделать, потому и вопрос такой задал.

Вообще, sev, вот Вам еще пища для размышлений:
http://oop.rosweb.ru/users/v/vbelkin/yaace.htm
Почитайте, думаю Вам будет интересно.
Re[3]: Re: Зачем надо throw new CMyException
От: SchweinDeBurg Россия https://zarezky.spb.ru/
Дата: 12.03.03 06:27
Оценка:
Здравствуйте, Borisman, Вы писали:

B>...использование СException, a, значит, привязка к MFC...


Там же свой CException определяется, причем здесь MFC?
- Искренне ваш, Поросенок Пафнутий
Re[4]: Re: Зачем надо throw new CMyException
От: Borisman  
Дата: 12.03.03 06:52
Оценка:
Здравствуйте, SchweinDeBurg, Вы писали:

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


B>>...использование СException, a, значит, привязка к MFC...


SDB>Там же свой CException определяется, причем здесь MFC?

Да, беру свои слова обратно. Есть там CException. Но там и CString есть, хотя это уже не принципиально — можно в конце концов подправить чуток и обойтись без MFC. Я так и сделаю, если автор будет не против.
Re[5]: Re: Зачем надо throw new CMyException
От: SchweinDeBurg Россия https://zarezky.spb.ru/
Дата: 12.03.03 06:57
Оценка:
Здравствуйте, Borisman, Вы писали:

B>...Но там и CString есть...

Есть у меня сильное подозрение, что CString там тоже авторский. Хотелось бы, конечно, услышать комментарии самого автора.
- Искренне ваш, Поросенок Пафнутий
Re[11]: Re[2]: Зачем надо throw new CMyException
От: Areex  
Дата: 12.03.03 07:31
Оценка:
Здравствуйте, Borisman, Вы писали:

B>Типичный пример, который вычитан мной из МСДН.

B>Пользователь должен авторизироваться при коннекте к серверу. Можно, конечно, сделать так:

B>
B>void Logon(const CString & name, const CString &passwd)
B>{
B>  ...
B>  if (!DB_HAS_ACCESS(name, passwd, currenttime, ...)) throw BadLogon();
B>}
B>


B>Но концептуально это глупо. Ведь неверное набирание пароля — дело лостаточно обычное, чего тут за голову хвататься и исключениями кидаться.

B>Лучше все-таки по старинке:

Чем глупо?
Именно так и надо делать. Концептуально функция должна возвращать результат, а не сообщение об ощибке.
"We charge!"
Re[6]: Зачем надо throw new CMyException
От: Аноним  
Дата: 12.03.03 07:36
Оценка:
Здравствуйте, Borisman, Вы писали:

B>Под влиянием общественности пришел в голову третий вариант — можно кидать объекты, ловить ссылки и вот эти ссылки(а не указатели) и оборачивать другими исключениями. Вот так надо и сделать, по-моему.


Не выйдет. В catch-блоке ты получаешь ссылку на временный, в сущности, объект. Сохранение ссылки на него — все одно, что сохранение ссылки на автоматический объект после выхода его из области видимости.
Re[11]: Re[2]: Зачем надо throw new CMyException
От: Ведмедь Россия  
Дата: 12.03.03 08:20
Оценка:
Здравствуйте, Borisman, Вы писали:


B>
B>void Logon(const CString & name, const CString &passwd)
B>{
B>  ...
B>  if (!DB_HAS_ACCESS(name, passwd, currenttime, ...)) throw BadLogon();
B>}
B>


B>Но концептуально это глупо. Ведь неверное набирание пароля — дело лостаточно обычное, чего тут за голову хвататься и исключениями кидаться.

B>Лучше все-таки по старинке:

B>
B>void Logon(const CString & name, const CString &passwd)
B>{
B>  ...
B>  return DB_HAS_ACCESS(name, passwd, currenttime, ...);
B>}
B>


B>Каждый инструмент должен использоваться по назначению.


НА мой взгляд в некоторых случаях наоборот. К примеру, если пароль проверяется в более глубоких функциях, то проверять каждый раз возвращяемое значение не особо читабельно, можно забыть его проверить, помнить, что кадый нумер ошибки значит и отдельно его обрабтывать. А исключение кинул "неверное имя или пароль" и тебя больше не волнует, а вдруг кто то заюыл проверить возвращяемый результат. Оно обработалось обработчиком нужного типа и т.п. и т.д.
Да пребудет с тобой Великий Джа
Re[12]: Re[2]: Зачем надо throw new CMyException
От: Borisman  
Дата: 12.03.03 08:39
Оценка:
Здравствуйте, Areex, Вы писали:

A>Чем глупо?

A>Именно так и надо делать. Концептуально функция должна возвращать результат, а не сообщение об ощибке.

Ошибка — тоже результат.

Тут нет, конечно, единого правила. Но все-таки не следует часто случающиеся ошибки кодировать исключениями. Все надо делать в соответствии со зравым смыслом, вот только здравый смысл у каждого свой
Re[13]: Re[2]: Зачем надо throw new CMyException
От: Areex  
Дата: 12.03.03 09:31
Оценка:
Здравствуйте, Borisman, Вы писали:

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


A>>Чем глупо?

A>>Именно так и надо делать. Концептуально функция должна возвращать результат, а не сообщение об ощибке.

B>Ошибка — тоже результат.


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

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


Ты не аргументировал, почему не следует. Обработка ошибок прямое назначение исключений. Этак половину c++ можно не использовать, мало ли у кого какой здравый смысл.
"It's only a naga."
Re[3]: Зачем надо throw new CMyException
От: Колян  
Дата: 12.03.03 09:49
Оценка:
Здравствуйте, Ведмедь, Вы писали:

К>>Если ты будешь передавать исключение дальше, да еще, завернув его в другое, то, возможно, второй подход будет лучше. Но я так никогда не делаю. И вообще не понимаю, суть обсуждения производительности блоков try-catch. Кому интересно, насколько быстро моя программа может сбоить???


В>Кстати не совсем верно. В данном вопросе да, производительность значения не имеет. Я тоже считаю, что если произошло исключение, то обработать его в 90 процентов случае время есть и можно уже не торопиться Но факт в том что try/catch не в лучшей сторону влияет на производительность, не зависимо от того, происходит или нет исключение. А вот это не приятно.


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

Этот блок стал занимать 12% от времени работы всего алгоритма! (измерял TrueTime-ом)

Конечно, я его убрал. И зарекся от использования исключений без надобности.
Так что, не наступайте на грабли
Re[3]: Re: Зачем надо throw new CMyException
От: sev http://www.demoforge.com
Дата: 12.03.03 10:19
Оценка:
sev>>Решение можно посмотреть в исходном тексте вот здесь:
sev>>http://www.demoforge.com/misc/SmartExceptions.h
> Да, действительно неплохо! Недостатка на самом деле два — второй -
> использование СException, a, значит, привязка к MFC. Но иначе все дела со
> снимком стека пришлось бы самому кодить. Очень, очень неплохо, мне
> понравилось. Именно что-то подобное я и хотел сам сделать, потому и вопрос
> такой задал.

СException там свой, если кого волнуют конфликты с MFC (я его не использую),
то можно погрузить это всё в namespace. CString взят из ATL/MFC 7.

Вообще говоря, структура самого СException здесь непринципиальна,
главное, что есть иерархия этих СException (соответственно, необходим
виртуальный деструктор) и дублирующая иерархия СExceptionPtr, чтобы
обеспечить полиморфизм в catch(). На самом деле СException это даже
не exception в том смысле, что его объекты никогда не бросаются

Касаемо new: подразумевается, что используется run-time с бросающим
new. Т.е. std::bad_alloc нужно ловить в отдельном catch, либо можно
унаследовать CExceptionPtr от std::exception, тогда ловить их все в одной
куче, но при этом не будет доступа к CException. В общем, не самая удачная
идея. Я предпочитаю реагировать на std::bad_alloc выбросом сообщения
"Шеф, усё пропало!" и не утруждать себя дальнейшей диагностикой.
Главное, что если мы собирались бросить исключение, то оно всё равно
бросится, даже если не сможет сконструироваться, правда в этом случае
уже бросится уже несколько другое исключение

> Вообще, sev, вот Вам еще пища для размышлений:

> http://oop.rosweb.ru/users/v/vbelkin/yaace.htm
> Почитайте, думаю Вам будет интересно.

Хм, весьма остроумно Особенно мне понравилась идея с выяснением
типа исключения, пойманного через catch (...). Перечитал стандарт, вроде
ничему не противоречит.

Правда, я не вижу смысла (для себя) решать те проблемы, которые перед
собой поставил автор этой статьи.

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

sev>После некоторых раздумий я реализовал решение, коим весьма теперь доволен.

sev>Все проблемы с автоматическим удалением исключения в нём решены, а также
sev>добавлена возможность "вложенности" исключений в стиле .NET.

sev>Решение можно посмотреть в исходном тексте вот здесь:

sev>http://www.demoforge.com/misc/SmartExceptions.h

sev>Теперь минусы: единственным отрицательным моментом, на мой взгляд, является

sev>то, что для каждого нового класса исключений нужно не забыть сделать один
sev>дополнительный typedef, благодаря которому появляется возможность пользоваться
sev>приведением к базовому классу в catch. В вышеприведённом коде видно, что мы
sev>ловим более абстрактное исключение, чем выбросили.

sev>Любые усовершенствования приветствуются


Мне кажется, что писать что-то вроде
    throw CMyExceptionPtr(new CMyException(...));

довольно неудобно. Вместо этого может имеет смысл сделать специальную функцию
template<class T>
CExceptionPtrT<T, typename T::inherited> wrapped_ptr(T *ptr) {
    return CExceptionPtrT<T, typename T::inherited>(ptr);
}

и использовать ее так
    throw wrapped_ptr(new CMyException(...));

или, даже написать такую
template<class T>
void throw_wrapped_ptr(T *ptr) {
    throw CExceptionPtrT<T, typename T::inherited>(ptr);
}


При этом, конечно, придется делать такой typedef для inherited (базового исключения) в определении исключения, но тогда можно избавиться от того "typedef'а в минусах".

--
Дмитрий
Re[6]: Re[2]: Hey, Hey, Hey
От: jazzer Россия Skype: enerjazzer
Дата: 12.03.03 12:15
Оценка:
Здравствуйте, Ведмедь, Вы писали:

В>Ну не всегда. в некоторых случаях IMHO прозрачней как раз через try/catch ( например, выход из N вложенных циклов )


тут уже был здоровенный флейм на эту тему :)))
Можно сказать, легенда RSDN :)))
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[6]: Зачем надо throw new CMyException
От: grs Россия  
Дата: 12.03.03 12:39
Оценка:
Здравствуйте, MaximE, Вы писали:

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


Нда. Похоже у меня в последнее время туго с выражением собственных мыслей. Так всегда бывает, когда занимаешься 4 делами одновременно.
Короче в том постинге, где ты мне 0 влепил я хотел сказать лишь следующее:
При выкидывании исключения нужно всегда использовать throw CMyExecption, а не throw new CMyExeption, а в блоке нужно писать catch(CMyExeption&), а не catch(CMyExeption) или catch(CMyExeption*). Иначе козленочком станешь. Рано или поздно. Только и всего. Хотя написал коряво, признаю.
Re[2]: Re: Зачем надо throw new CMyException
От: grs Россия  
Дата: 12.03.03 12:43
Оценка:
Здравствуйте, sev, Вы писали:


sev>А ниже показано, как это решение работает "в жизни".


sev>void ThrowingFunc()

sev>{
sev>throw CSystemExceptionPtr(new CSystemException(E_FAIL));
sev>}

sev>Самое главное, что код абсолютно безопасен (я так думаю во всяком случае


А я не понял, а что будет если при вызове ThrowingFunc new выкинет скажем std::bad_alloc? Все-таки не нравится мне эта идея с динамическим выделением памяти при генерации исключения. Проще надо ИМХО, конечно.
Re[14]: Re[2]: Зачем надо throw new CMyException
От: Borisman  
Дата: 12.03.03 12:47
Оценка:
A>Нет, ошибка это ошибка. Функция же может только вернуть результат, который можно трактовать как ошибку.

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

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


Не следует использовать средства языка только потому, что они есть. Если нет смысла в применении половины С++ — значит, так тому и быть. Когда Вы в последний раз применяли оператор , (запятая) ?
... << RSDN@Home 1.0 beta 6a >>
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;
}

А вообще-то "," в циклах очень часто встречается в сложных итераторах...
Голь на выдумку хитра, однако...
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.