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


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


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

А вообще, есть книжки Страуструпа (естественно) и Мейерса, где все расписано. Надо просто достать и прочитать внимательно. А резюме такое:
1) выбрасывается ТОЛЬКО стековый объет (НИ В КОЕМ СЛУЧАЕ НЕ УКАЗАТЕЛЬ)
2) перехватывается ССЫЛКА (не значение!).
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
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.