Исключения или коды возврата?
От: Bell Россия  
Дата: 11.09.02 10:11
Оценка:
Сабж навеян топиком "Как это сделать" из форума по С++.
Началось все с того, что Юнусов Булат сказал:

atoi в серьезных прогах вообще лучше не использовать - при невозможности конвертации она ексепшенсы не 
отбрасывает, другими словами прога будет работать до первой неудачной конвертации - потом начнет 
выдавать крутой бред.

С чем я полностью согласен.
На это Vladik ответил , что
Ненавижу эксепшины. (На мой взгляд слабый аргумент)
atoi просто тихо вернет 0. А если я эксепшин в нужном месте не отловлю - тогда да, действительно будет весело.


Но собственно дело конечно же не в atoi (вернее не только в atoi). Дело в принципе — использовать, или не использовать исключения (ну или коды возврата)?

На мой вгляд глупо было бы отдавать предпочтение либо только исключениям, либо только кодам возврата, ибо назначение у этих двух механизмов несколько разное.
Я конечно не открою америку, если скажу, что коды возврата следует использовать тогда, когда есть готовый вариант поведения или готовая реакция на некоторое нестандартное событие. Ну например неправильный ввод данных. Можно спокойно проигнорировать некорректные данные, заменив их чем-то осмысленным(конечно если это допустимый вариант поведения), можно оповестить об этом пользователя и попросить его повторить ввод. Исключения для этого вовсе не обязательны. Главное — чтобы была возможность распознать некорректность данных на нужном этапе (в случае с пресловутой atoi сделать это без дополнительных усилий нельзя), и выбрать нужный вариант поведения.
Теперь рассмотрим такую ситуацию:
Идет формирование некоторой сложной модели, которая весьма чувствительна к корректности исходных данных (любое несоответствие делает дальнейшую работу ненужной). Зачем мне в куче мест вставлять проверки на значения кодов возврата сервисных функций, после чего просто говорить return? Да делать это еще по всему дереву вызовов? Не проще ли выкинуть исключение из этой сервисной функции, и поймать его на верхнем уровне?
ИМХО код будет несколько проще и понятнее.

Ну так вот, а что думает общественность по этому поводу?
Как мне уже сказали, у меня найдется множество аппонентов
Надеюсь, что и сторонников будет не меньше
Любите книгу — источник знаний (с) М.Горький
Re: Исключения или коды возврата?
От: Юнусов Булат Россия  
Дата: 11.09.02 10:19
Оценка:
Здравствуйте Bell, Вы писали:

Время все уже расставило по своим местам.
Народ потянулся в дотнет — тама ексепшенсы рулят.
Re: Исключения или коды возврата?
От: Torero2002 Россия  
Дата: 11.09.02 10:22
Оценка:
И все-таки эксепшены. Аргументы: информативно, удобно, читабельно. Особенно это актуально при COM разработке — очень часто одного кода возврата бывает мало, более того большинство просто возвращает E_FAIL про который вообще ничего нельзя сказать.

А по поводу:

"Ненавижу эксепшины. (На мой взгляд слабый аргумент)
atoi просто тихо вернет 0. А если я эксепшин в нужном месте не отловлю — тогда да, действительно будет весело"

могу сказать следующее: если ты этот тихий ноль не отловишь, то проблем будет не меньше.
Smart? Prove it!
Re: Исключения или коды возврата?
От: SiGMan / iO UpG Южная Корея www.ioupg.com
Дата: 11.09.02 10:37
Оценка:
Иногда ИМХО удобнее сочетать оба способа
А с проверкой кода ошибки можно поступить следующим образом:
Поиметь легкий класс вокруг enum ошибок. В класса есть дополнительный флаг — "проверенно" ( мин нет, Сапер Сидоров ) Оператор равенства ( и неравенства заодно ) сбрасывает этот флаг. В деструкторе имеется проверка на наличие ошибки ( код ошибки != ОК ) и взведенного флага ( не проверил, скотина! ) и там выбрасывать исключение или поставить assert. Т.к. для клиента класса данная обертка будет прозрачна ( в смысле, тоже самое что и enum ) то потом ( после отладки итд ) его можно будет просто заменить на этот самный enum.
Т.е. как это выглядит в коде:
( пример применения )
class MyClass {
public:
    enum Results 
    {
        RES_UNKNOWN            = 1,
        RES_ERROR1,
        RES_FATALERROR,
        RES_MINDBLOWNERROR,
        RES_MAX
    };
    

    static const ResultTable results[ RES_MAX ];
    typedef ResultClass< results, Results > Result;
    
    // 
    
    Result SomeMethod() 
    {
        if ( bad_bad ) {
            return RES_ERROR1;
        }
        
        return OK;
    }
};
....
MyClass obj;
if ( obj.SomeMethod() != OK ) .... /// тут все будет ок
...
obj.SomeMethod(); /// а тут при возврате кода ошибки отличного от ОК, произойдет assert


Система, конечно, не без недостатков, но вдруг кому-то понадобится...
io /l、 
゙(゚、 。 7
 l、゙ ~ヽ
 じしf_, )ノ
Re[2]: Исключения или коды возврата?
От: Admiral Украина  
Дата: 11.09.02 11:22
Оценка:
Здравствуйте Юнусов Булат, Вы писали:

ЮБ>Здравствуйте Bell, Вы писали:


ЮБ>Время все уже расставило по своим местам.

ЮБ>Народ потянулся в дотнет — тама ексепшенсы рулят.

Но MS рекомендует ими не увлекаться.
Performance Tips and Tricks in .NET Applications
Re[2]: Исключения или коды возврата?
От: Lexey Россия  
Дата: 11.09.02 11:55
Оценка:
Здравствуйте Torero2002, Вы писали:

T>И все-таки эксепшены. Аргументы: информативно, удобно, читабельно. Особенно это актуально при COM разработке — очень часто одного кода возврата бывает мало, более того большинство просто возвращает E_FAIL про который вообще ничего нельзя сказать.


Так-так, нужно сюда Влада позвать. Он подробно расскажет, почему эксепшены в COM'е — это плохое решение. А коды возврата к делу не имеют никакого отношения — никто не мешает надефайнить кучу своих кодов возврата (что, кстати, придется делать и при использовании эксепшенов).

T>А по поводу:


T>"Ненавижу эксепшины. (На мой взгляд слабый аргумент)

T>atoi просто тихо вернет 0. А если я эксепшин в нужном месте не отловлю — тогда да, действительно будет весело"

T>могу сказать следующее: если ты этот тихий ноль не отловишь, то проблем будет не меньше.


Сильно зависит от задачи.

Мое личное мнение — эксепшены хороши в клиентском коде. В серверном коде (и особенно в COM-серверах) им не место.
"Будь достоин победы" (c) 8th Wizard's rule.
Re[3]: Исключения или коды возврата?
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 11.09.02 12:02
Оценка: 32 (1) +2
Здравствуйте Admiral, Вы писали:

A>Но MS рекомендует ими не увлекаться.

A>Performance Tips and Tricks in .NET Applications

MS понятие растяжимое. Это советует конкретный сотрудник. И надо всегда относиться к этому с оглядкой.
Вот смотри. Это тот пример который он привел
public static void Main(string[] args){
  int j = 0;
  for(int i = 0; i < 10000; i++){
    try{   
      j = i;
      throw new System.Exception();
    } catch {}
  }
  System.Console.Write(j);
  return;   
}


А это моя переделка, ибо то что он предлагает оценивать на глаз, та еще с таким малым количеством итераций это поленйший маразм.
public static void Main(string[] args){
  int j = 0;

  int st;
  //Подождем чтобы система устаканилась после загрузки
  System.Threading.Thread.Sleep(1000);
  st = Environment.TickCount;
  for(int i = 0; i < 1000000; i++){
    try{   
      j = i;
      throw new System.Exception();
    } catch {}
  }
  Console.WriteLine((double)(Environment.TickCount-st)/1000000+" ms per cycle");
}


Результат выполения на средненькой по нынешним временам машинке (Celeron 1000) дает такой результат

0,015993 ms per cycle

Т.е. на вызов одного эксепшена вместе с присваиванием уходит меньше двух стотысячных секунды. И это он называет "tremendous overhead"? Даже не смешно. Чтобы это почувствовать надо генерить десятки тысяч эксепшенов в секунду.
... << J 1.0 alpha 4 >>
AVK Blog
Re[3]: Исключения или коды возврата?
От: Bell Россия  
Дата: 11.09.02 12:21
Оценка:
Здравствуйте Lexey, Вы писали:

L>Так-так, нужно сюда Влада позвать. Он подробно расскажет, почему эксепшены в COM'е — это плохое решение. А коды возврата к делу не имеют никакого отношения — никто не мешает надефайнить кучу своих кодов возврата (что, кстати, придется делать и при использовании эксепшенов).

Можно подробнее — что я должен дефайнить при использовании исключений?
...
L>Сильно зависит от задачи.
Естественно. О чем я и говорил. Если есть допустимый вариант поведения при (возможном) возникновении некоторой нестандартной ситуации — значит это не исключительная ситуация.

L>Мое личное мнение — эксепшены хороши в клиентском коде. В серверном коде (и особенно в COM-серверах) им не место.

А вот в CORBA зачем-то предусмотрены механизмы выброса исключений из серверов и последующей их обработки на клиентах...
Любите книгу — источник знаний (с) М.Горький
Re[4]: Исключения или коды возврата?
От: George Seryakov Россия  
Дата: 11.09.02 13:42
Оценка:
Здравствуйте Bell, Вы писали:

L>>Так-так, нужно сюда Влада позвать. Он подробно расскажет, почему эксепшены в COM'е — это плохое решение.


Ой, нужно.

L>>А коды возврата к делу не имеют никакого отношения — никто не мешает надефайнить кучу своих кодов возврата (что, кстати, придется делать и при использовании эксепшенов).

B>Можно подробнее — что я должен дефайнить при использовании исключений?

Способы передать информацию об ошибке. Либо однотипный класс исключения и куча кодов возврата, либо куча классов исключения.

L>>Мое личное мнение — эксепшены хороши в клиентском коде. В серверном коде (и особенно в COM-серверах) им не место.


B>А вот в CORBA зачем-то предусмотрены механизмы выброса исключений из серверов и последующей их обработки на клиентах...


Да. И еще нет никого другого способа обработать ошибку в конструкторе класса. Но просто-напросто все ошибки компилятора, которые я встречал в 6-ке, были связаны с обработкой исключений.
GS
Re[3]: Исключения или коды возврата?
От: Torero2002 Россия  
Дата: 11.09.02 13:52
Оценка:
Здравствуйте Lexey, Вы писали:

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


T>>И все-таки эксепшены. Аргументы: информативно, удобно, читабельно. Особенно это актуально при COM разработке — очень часто одного кода возврата бывает мало, более того большинство просто возвращает E_FAIL про который вообще ничего нельзя сказать.


L>Так-так, нужно сюда Влада позвать. Он подробно расскажет, почему эксепшены в COM'е — это плохое решение. А коды возврата к делу не имеют никакого отношения — никто не мешает надефайнить кучу своих кодов возврата (что, кстати, придется делать и при использовании эксепшенов).


Коды возврата в COM, на мой взгляд, значит примерно одно тоже: либо ты послан, либо нет. Ведь не даром "умные дядьки" из Microsoft и в comdef.h и в ATL ввели интерфейсы/классы поддержки COM исключений. Хотя послушать аргументы в пользу использования кодов возврата в COM я бы послушал.

T>>А по поводу:


T>>"Ненавижу эксепшины. (На мой взгляд слабый аргумент)

T>>atoi просто тихо вернет 0. А если я эксепшин в нужном месте не отловлю — тогда да, действительно будет весело"

T>>могу сказать следующее: если ты этот тихий ноль не отловишь, то проблем будет не меньше.


L>Сильно зависит от задачи.


L>Мое личное мнение — эксепшены хороши в клиентском коде. В серверном коде (и особенно в COM-серверах) им не место.
Smart? Prove it!
Re[5]: Исключения или коды возврата?
От: Bell Россия  
Дата: 11.09.02 14:29
Оценка:
Здравствуйте George Seryakov, Вы писали:

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


L>>>Так-так, нужно сюда Влада позвать. Он подробно расскажет, почему эксепшены в COM'е — это плохое решение.


GS> Ой, нужно.


С СОМ я практически не работаю, но аргументированное мнение выслушать всегда готов. Кто знает, может и сгодится в будущем...

GS> Способы передать информацию об ошибке. Либо однотипный класс исключения и куча кодов возврата, либо куча классов исключения.


Ладно, это была просто придирка
От этого никуда не деться — информацию об ошибке все равно нужно передавать. Либо код возврата, либо тип исключения, либо некоторая их комбинация.
Но главное все-таки не способ представления информации об ошибке, а способ передачи этой информации.
Как я уже говорил — я не призываю всех отказаться от использования кодов возврата, и начать использовать только исключения. Это просто глупо. Главное — грамотно разобраться где использовать исключение, а где обработать код возврата. ИМХО такой код проще
void somefunc()
{
   ...
   if(bSomeCondition)
      throw SomeException();
}

void f1()
{
...
   somefunc();
}
void f2();
...
void fn();

void g()
{
   f1();
   f2();
   ...
   somefunc();
}

void d()
{
   try
   {
      g();
   }
   catch(SomeException& e)
   {
   ...
   }
}

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

Так же просто можно придумать пример, в котором использование исключений ведет к усложнению и снижению эффективности.
ИМХО главное — это хорошенько подумать, а не говорить "не люблю я исключения (коды возврата), поэтому не буду их использовать". Именно это я и хотел сказать с самого начала

GS> Да. И еще нет никого другого способа обработать ошибку в конструкторе класса. Но просто-напросто все ошибки компилятора, которые я встречал в 6-ке, были связаны с обработкой исключений.

Ну так у ж и все? Ошибок, связанных с использованием шаблонов тоже хватает. Однако это не повод отказаться от их использования... Хотя это (наличие ошибок) конечно же весьма огорчает
Любите книгу — источник знаний (с) М.Горький
Re[4]: Исключения или коды возврата?
От: Mink Россия  
Дата: 12.09.02 07:34
Оценка: 4 (1)
Здравствуйте Bell, Вы писали:


L>>Мое личное мнение — эксепшены хороши в клиентском коде. В серверном коде (и особенно в COM-серверах) им не место.

B>А вот в CORBA зачем-то предусмотрены механизмы выброса исключений из серверов и последующей их обработки на клиентах...

А в COM предусмотрен интерфейс IErrorInfo, через который и рекомедуется передавать информацию об ошибках семантического характера. А код возврата HRESULT использовать только для сообщения о наличии ошибки. Передавать через HRESULT свой код нехорошо, поскольку HRESULT используется еще и для сообщения об ошибках системного плана, которые могут возникать при работе системного слоя поддержки COM.

А эксепшены в COMе плохое решение именно потому, что в нем нет такого механизма их передачи через границу процесса
Сила, она в ньютонах
Re: Исключения или коды возврата?
От: Nikita Dolgov Россия http://nikitadolgov.narod.ru/
Дата: 12.09.02 09:32
Оценка: 26 (2)
Здравствуйте Bell,

ИМХО данный документ настолько хорош, что практически закрывает тему:

http://www.objectarchitects.de/arcus/cookbook/exhandling/index.htm
Old C programmers never die. They're just cast into void.
Re: Все зависит от системы
От: Снорк  
Дата: 17.09.02 07:47
Оценка:
Нет такой идеи, которую нельзя было бы испоганить. Исключения, коды возврата — один хрен в этом смысле.

Хороший пример из COM — с параметрами [out, retval]. Что происходит при генерации wrapper'а? На сях — каждый метод и свойство дублируются — методы — raw, свойства — Get/Set. Хочешь обрабатывать коды возврата — флаг тебе в руки, хочешь ловить исключения — тоже вперед и с песней. Вот это продуманная вещь.

А есть такие системы, не будем тыкать пальцами, где что ни идея, то глюк в реализации.

Хочу спросить — а какие есть мнения по аналогичному вопросу: IErrorInfo сотоварищи vs. GetLastErrorInfo? (Тексты и коды передаются вместе).
Re[4]: Исключения или коды возврата?
От: WPooh США  
Дата: 20.09.02 18:13
Оценка:
Здравствуйте AndrewVK, Вы писали:

Не спора ради, а уточнения для.
AVK>А это моя переделка, ибо то что он предлагает оценивать на глаз, та еще с таким малым количеством итераций это поленйший маразм.
Пример действительно не демонстрирует никакого overhead-а.
IMHO, проблема возникает при раскрутке стека вызовов с поиском ближайшего обработчика исключений.
Может оно сейчас эффективней реализуется, прогресс ушел дальше...

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

AVK>Результат выполения на средненькой по нынешним временам машинке (Celeron 1000) дает такой результат

Не такая она и средненькая.

Успехов!
К этому моменту у меня внутри 0.5, 0.7, 0.33 (с) НС
Re[5]: Исключения или коды возврата?
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 20.09.02 18:20
Оценка:
Здравствуйте WPooh, Вы писали:

WP>IMHO, проблема возникает при раскрутке стека вызовов с поиском ближайшего обработчика исключений.

WP>Может оно сейчас эффективней реализуется, прогресс ушел дальше...

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

AVK>>Результат выполения на средненькой по нынешним временам машинке (Celeron 1000) дает такой результат

WP>Не такая она и средненькая.

Но студия на ней работает на пределе. По крайней мере разница между ним и AXP 2000+ разительная. Правда на атлоне памяти не 256 а 512 и память DDR333.
... << Янус 1.0 alpha 7 (developers build) >>
AVK Blog
Re[6]: Исключения или коды возврата?
От: WPooh США  
Дата: 23.09.02 04:55
Оценка:
Здравствуйте AndrewVK, Вы писали:

AVK>Ну дядька то в той статье говорил что главный оверхед именно на создание ексепшена идет. А что касаемо раскрутки стека — если приложение грамотно спроектировано то в тех ситуациях когда исключение генериться часто стек до первого кетча будет совсем коротенький.


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

AVK>>>Результат выполения на средненькой по нынешним временам машинке (Celeron 1000) дает такой результат

WP>>Не такая она и средненькая.

AVK>Но студия на ней работает на пределе. По крайней мере разница между ним и AXP 2000+ разительная. Правда на атлоне памяти не 256 а 512 и память DDR333.

Это-твоя машинка. Разработчика. А есть машинки у клиентов. У них может вообще стоять старый пень 100 мегагерцовый с 64 SIMM.
[off]у нас и некоторых разработчиков не уважают — года по три машины не меняют, гады.[/off]
К этому моменту у меня внутри 0.5, 0.7, 0.33 (с) НС
Re[5]: Исключения или коды возврата?
От: adb Россия  
Дата: 30.09.02 05:25
Оценка:
Здравствуйте WPooh, Вы писали:

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


WP>Не спора ради, а уточнения для.

AVK>>А это моя переделка, ибо то что он предлагает оценивать на глаз, та еще с таким малым количеством итераций это поленйший маразм.
WP>Пример действительно не демонстрирует никакого overhead-а.
WP>IMHO, проблема возникает при раскрутке стека вызовов с поиском ближайшего обработчика исключений.
WP>Может оно сейчас эффективней реализуется, прогресс ушел дальше...

WP>Вроде бы даже название говорит о том, что этой техникой предполагалось пользоваться в редких (исключительных) случаях.



Эффективней некуда. В том то вся и прелесть текущей реализации, что оверхэд возникает _только_ при выбрасывании исключения. Потому и советуют их выбрасывать в действительно исключительных ситуациях. Раньше не знаю как у всех, но по крайней мере в нашем компиляторе реализовывалась схема setjmp/longjmp — что дает просто существенный оверхед при _нормальной работе_. Плюс еще и создаются специальные таблицы в сегменте данных, с помошью которых находят обработчики исключений. Собственно поэтому во встроенных системах и реал-тайме, где размер и время работы даже в исключительных ситуациях на вес золота, исключений стараются избегать.
Re[6]: Исключения или коды возврата?
От: WPooh США  
Дата: 01.10.02 07:39
Оценка:
Здравствуйте adb, Вы писали:

adb>Эффективней некуда. В том то вся и прелесть текущей реализации, что оверхэд возникает _только_ при выбрасывании исключения. Потому и советуют их выбрасывать в действительно исключительных ситуациях. Раньше не знаю как у всех, но по крайней мере в нашем компиляторе реализовывалась схема setjmp/longjmp — что дает просто существенный оверхед при _нормальной работе_. Плюс еще и создаются специальные таблицы в сегменте данных, с помошью которых находят обработчики исключений. Собственно поэтому во встроенных системах и реал-тайме, где размер и время работы даже в исключительных ситуациях на вес золота, исключений стараются избегать.


Вот про ваш компилятор — кто это такой, расскажите плиз. Ну или намекните.
Вот у меня вопрос как к специалисту. По стандарту говорится, что деструкторы должны отработать для всех корректно созданных объектов с момента вхождения в try соответствующей ловушки. Как вы осуществляли вызовы деструкторов? Я что-то посмотрел в стандарт, не нашел слов по поводу того, что указатель на деструктор находится первым в таблице методов класса. Да, ежели он виртуальный — он должен быть в vtbl. На этот счет есть флажок или всегда генерируете vtbl и помещаете туда указатель на деструктор в любом случае, вне зависимости от того, виртуальный он или нет? Ну это мелочь, собственно.
А вот более интересно, как определяете какие именно объекты были сконструированы — раскруткой стека и анализом кода? Просто если при нормальной работе overhead-а нет, значит, никакие списки сконструированных объектов не генерируются. Тогда получается, что самая тяжелая операция — анализ на предмет сгенерированных объектов и вызов деструкторов. Это так?
Заранее благодарен за ответ.
К этому моменту у меня внутри 0.5, 0.7, 0.33 (с) НС
Re[7]: Исключения или коды возврата?
От: Anatolix Россия https://www.linkedin.com/in/anatolix/
Дата: 01.10.02 08:11
Оценка:
Здравствуйте WPooh, Вы писали:

WP>Вот про ваш компилятор — кто это такой, расскажите плиз. Ну или намекните.

WP>Вот у меня вопрос как к специалисту. По стандарту говорится, что деструкторы должны отработать для всех корректно созданных объектов с момента вхождения в try соответствующей ловушки. Как вы осуществляли вызовы деструкторов? Я что-то посмотрел в стандарт, не нашел слов по поводу того, что указатель на деструктор находится первым в таблице методов класса. Да, ежели он виртуальный — он должен быть в vtbl. На этот счет есть флажок или всегда генерируете vtbl и помещаете туда указатель на деструктор в любом случае, вне зависимости от того, виртуальный он или нет? Ну это мелочь, собственно.
WP>А вот более интересно, как определяете какие именно объекты были сконструированы — раскруткой стека и анализом кода? Просто если при нормальной работе overhead-а нет, значит, никакие списки сконструированных объектов не генерируются. Тогда получается, что самая тяжелая операция — анализ на предмет сгенерированных объектов и вызов деструкторов. Это так?

Деструкторы вызываются для локальных переменных. Их настоящий тип
известен на момент компиляции и проблем с виртуальностью едесь нет никаких.

Если же ты создал объект по new сам его и грохни. Не хочешь возиться с исключениями auto_ptr тебе в помощь.
Любая проблема дизайна может быть решена введением дополнительного абстрактного слоя, за исключением проблемы слишком большого количества дополнительных абстрактных слоев
Re[8]: Исключения или коды возврата?
От: WPooh США  
Дата: 01.10.02 10:52
Оценка:
Здравствуйте Anatolix, Вы писали:

A>Деструкторы вызываются для локальных переменных. Их настоящий тип

A>известен на момент компиляции и проблем с виртуальностью едесь нет никаких.

A>Если же ты создал объект по new сам его и грохни. Не хочешь возиться с исключениями auto_ptr тебе в помощь.

Ага, это я знаю. Речь совсем не об этом.
Меня интересует не методика написания программ для корректной обработки исключений и освобождения ресурсов, занятых программой, а как компилятор реализует стандарт. Ну, пусть гипотетический компилятор, не в конкретной инкарнации.
Допустим да, есть у нас таблица всех обработчиков исключений, реализованных в программе — сигнатура исключения и список точек входа в соответствующие ловушки.
А вот мне не понятно то, каким образом происходит поиск объектов, сконструированных с момента входа в блок try той ловушки (соответствующей кинутому исключению), которую мы нашли ближайшей для нашего исключения (хотя это тоже нетривиальный момент, без раскрутки стека не обойдется, просто анализ упростится при помощи этой таблицы). Эту вещь я примерно представляю.

Но вот поиск всех сгенеренных объектов между этими двумя точками — тоже собственно, раскрутка стека и анализ кода процедур (ага, вот тут положили на стек пару int-ов и HANDLER — смещаем стек назад. А вот тут у нас заведен класс типа MyClass — нужно позвать деструктор). Деструкторы объектов на стеке компилятор вызывает при нормальном выходе из блока При бросании исключения, видимо, проще тоже позвать их же, но нужно анализировать branch-и разных ветвлений и пр. ерунду. Просто так передать управление на какую-то точку нельзя, нам же просто нужно деструкторы вызвать, а не продолжить работу — после этого блока может идти дальнейшая обработка данных. С другой стороны, код-то уже есть, нужно просто понять где деструкторы заканчиваются и где начинаются деструкторы другого блока, более объемлющего для данной ветки программы.
То ли помещать проверку после каждого окончания блока — а кинули ли исключение? Да — идем на следующий кусок с деструкторами : нет — продолжаем работу.

Например,
long MyMainFunc()
{
  MyClass1 mObj;
  try
  {
    MyClass2 mObj2;
    long lVal = 1;
    char pBuff[1024];
    MyFunc1(1); // can throw exception
  }
  catch(...)
  {
  }
}

long MyFunc1(long param)
{
  MyClass100 mObj100(param);
  if (param>2000)
    return -1;
  if ((param&0x1)==0x1)
  {// pp_1
    MyClass3 mObj3(param);
    long ind=0;
    char pBuff[4];
    if (MyFunc2(param++)==3)// point1
      mObj3.SomeFunc(param);
    else
      mObj3.SomeFunc(param+2);
  } // p_1
  else
  {
    MyClass4 mObj4(param);
    MyFunc2(++param);// point2
    mObj4.OtherFunc(param);
  } //p_2
  MyClass5 mObj5(param);
  mObj5.OtherCoolFunction;
}// p_3

long MyFunc2(long param) throw myException
{
  if (param>1500)
    throw new myException(param);
  param += 5;
  MyFunc1(param);//point3
}// p_4

Я для нагладности привел взаимную рекурсию из двух функций.
В конце концов кинется исключение. То есть, вызовется специальная функция рантайма.
Допустим, есть таблица с указателями на обработчики — там нашли вхождение myException.
В точках point1, point2 и point3 будем находиться во время выхода из функций при раскрутке стека назад.
В точках p_1, p_2, p_3 и p_4 расположен код вызова нужных нам деструкторов. Вот собственно, проблема — то ли раскручивать код назад (допустим, находимся в point1 — назад до точки pp_1 докрутим, а дальше? Анализировать условия ветвления?), то ли прыгать на деструкторы (эти точки p_X еще надо найти).
Видимо, все-таки строится список сконструированных объектов.
Это мое видение, оно может сильно отличаться от истины. Вот я и хотел спросить знатока, как оно внутри устроено. Там же еще наверняка тонкостей выше крыши. Со списками жизнь проще при выкидывании исключения, но есть overhead при нормальной работе.
Это чисто теоретический интерес, не имеющий никакого прикладного значения.

А как работать с файловыми HANDLE, чтобы при генерации исключения файлики закрывались, GDI и прочие ресурсы освобождать — я не это имел в виду. Спасибо, но немножко не оно.

Если запутанно — извините. Можно поконкретнее пообсуждать. Только вот подозреваю, вопрос не будет обсуждаться. Ибо зачем?
Успехов!
К этому моменту у меня внутри 0.5, 0.7, 0.33 (с) НС
Re[9]: Исключения или коды возврата?
От: Anatolix Россия https://www.linkedin.com/in/anatolix/
Дата: 01.10.02 11:26
Оценка: -1
Здравствуйте WPooh, Вы писали:

WP>Если запутанно — извините. Можно поконкретнее пообсуждать. Только вот подозреваю, вопрос не будет обсуждаться. Ибо зачем?


Действительно. если никогда не наблюдал то возьми дизассемблер да посмотри.
Любая проблема дизайна может быть решена введением дополнительного абстрактного слоя, за исключением проблемы слишком большого количества дополнительных абстрактных слоев
Re[10]: Исключения или коды возврата?
От: WPooh США  
Дата: 01.10.02 12:55
Оценка:
Здравствуйте Anatolix, Вы писали:

A>Действительно. если никогда не наблюдал то возьми дизассемблер да посмотри.

Спасибо за совет. Посмотрю на досуге.

Ежели появится adb буду рад с ним поболтать.
Кстати, adb, ты не из XDS случаем?
К этому моменту у меня внутри 0.5, 0.7, 0.33 (с) НС
Re[11]: Исключения или коды возврата?
От: Аноним  
Дата: 01.10.02 13:39
Оценка:
Здравствуйте WPooh, Вы писали:

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


A>>Действительно. если никогда не наблюдал то возьми дизассемблер да посмотри.

WP>Спасибо за совет. Посмотрю на досуге.

WP>Ежели появится adb буду рад с ним поболтать.

WP>Кстати, adb, ты не из XDS случаем?

Уже нет -)). Два года назад ушел оттуда.

Собственно я далеко не специалист в этой области. Во-вторых они пишут Java native compiler. А в натуральной Java такой проблемы в принципе нету. Там все объекты создаются в куче и рулятся gc'ом. В XDS компиляторе научились таки в некоторых случаях размешать объекты на стеке, поэтомуй как-то они эту проблему решили. В принципе попробую посмотреть или тупо спросить.

А вообще могу статейку кинуть, которая так и называется "Zero-Overhead Exception Handling Using Metaprogramming", либо в инете её поищи.
Re: Про эффективность.
От: _Winnie Россия C++.freerun
Дата: 11.05.06 14:09
Оценка:
VC71.


конструктор Object при включённых исключениях:

    Object() {}
00401040  push        0FFFFFFFFh 
00401042  push        offset __ehhandler$??0Object@@QAE@XZ (405D59h) 
00401047  mov         eax,dword ptr fs:[00000000h] 
0040104D  push        eax  
0040104E  mov         dword ptr fs:[0],esp 
00401055  push        ecx  
00401056  push        esi  
00401057  mov         esi,ecx 
00401059  mov         dword ptr [esp+4],esi 
0040105D  call        Subobject::Subobject (401000h) 
00401062  lea         ecx,[esi+1] 
00401065  mov         dword ptr [esp+10h],0 
0040106D  call        Subobject::Subobject (401000h) 
00401072  lea         ecx,[esi+2] 
00401075  mov         byte ptr [esp+10h],1 
0040107A  call        Subobject::Subobject (401000h) 
0040107F  lea         ecx,[esi+3] 
00401082  mov         byte ptr [esp+10h],2 
00401087  call        Subobject::Subobject (401000h) 
0040108C  lea         ecx,[esi+4] 
0040108F  mov         byte ptr [esp+10h],3 
00401094  call        Subobject::Subobject (401000h) 
00401099  mov         ecx,dword ptr [esp+8] 
0040109D  mov         eax,esi 
0040109F  pop         esi  
004010A0  mov         dword ptr fs:[0],ecx 
004010A7  add         esp,10h 
004010AA  ret



метод Object2::Init при выключенных исключениях:


    bool Init()
    {
00401020  push        esi  
00401021  push        edi  
00401022  mov         esi,ecx 
        if (!a.Init()) goto error;
00401024  call        Subobject2::Init (401000h) 
00401029  test        al,al 
0040102B  je          error (40105Eh) 
        if (!b.Init()) goto error;
0040102D  lea         edi,[esi+1] 
00401030  mov         ecx,edi 
00401032  call        Subobject2::Init (401000h) 
00401037  test        al,al 
00401039  je          error (40105Eh) 
        if (!c.Init()) goto error;
0040103B  lea         ecx,[esi+2] 
0040103E  call        Subobject2::Init (401000h) 
00401043  test        al,al 
00401045  je          error (40105Eh) 
        if (!b.Init()) goto error;
00401047  mov         ecx,edi 
00401049  call        Subobject2::Init (401000h) 
0040104E  test        al,al 
00401050  je          error (40105Eh) 
          if (!e.Init()) goto error;
00401052  lea         ecx,[esi+4] 
00401055  call        Subobject2::Init (401000h) 
0040105A  test        al,al 
0040105C  jne         error+2Dh (40108Bh) 
error:
        Shutdown();
0040105E  mov         ecx,esi 
00401060  call        Subobject2::Shutdown (401010h) 
00401065  lea         edi,[esi+1] 
00401068  mov         ecx,edi 
0040106A  call        Subobject2::Shutdown (401010h) 
0040106F  lea         ecx,[esi+2] 
00401072  call        Subobject2::Shutdown (401010h) 
00401077  mov         ecx,edi 
00401079  call        Subobject2::Shutdown (401010h) 
0040107E  lea         ecx,[esi+4] 
00401081  call        Subobject2::Shutdown (401010h) 
00401086  pop         edi  
        return false;
00401087  xor         al,al 
00401089  pop         esi  
    }
0040108A  ret              
0040108B  pop         edi  
        return true;
0040108C  mov         al,1 
0040108E  pop         esi  
    }
0040108F  ret


















// test.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

int i;



//--------------------------

struct Subobject
{
    __declspec(noinline)Subobject() { if(rand()) throw 0; ++i; }
    __declspec(noinline) ~Subobject() { ++i; }
};

struct Object
{
    Subobject a, b, c, d, e;

    Object() {}
    ~Object() {}
};

void __declspec(noinline) f()
{
    Object a;
}

//--------------------------

struct Subobject2
{
    __declspec(noinline) bool Init() { return rand();  }
    __declspec(noinline) Shutdown() { return rand();  }
};

struct Object2
{
    Subobject2 a, b, c, d, e;

    bool Init()
    {
        if (!a.Init()) goto error;
        if (!b.Init()) goto error;
        if (!c.Init()) goto error;
        if (!b.Init()) goto error;
        if (!e.Init()) goto error;
        return true;
error:
        Shutdown();
        return false;
    }

    void Shutdown() 
    { 
        //объекты Subobject должны быть готовы к Shutdown без инициализации, 
        //что ещё больше усиливает syntax-клаттер и увеличивает asm-код.
        a.Shutdown();
        b.Shutdown(); 
        c.Shutdown();
        b.Shutdown();
        e.Shutdown();
    }
};


bool __declspec(noinline) g()
{
    Object2 b;
    if (b.Init())
        return false;
}


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

    if (!g())
        return 1;
}
Правильно работающая программа — просто частный случай Undefined Behavior
Re[7]: Исключения или коды возврата?
От: Max.Subpixel Россия  
Дата: 12.05.06 12:03
Оценка:
Здравствуйте, WPooh, Вы писали:

WP>Это-твоя машинка. Разработчика. А есть машинки у клиентов. У них может вообще стоять старый пень 100 мегагерцовый с 64 SIMM.

WP>[off]у нас и некоторых разработчиков не уважают — года по три машины не меняют, гады.[/off]

Даже если три года не менять машину — такого старья быть не может...
На такой машине Win 2000 работает очень с трудом....
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Best Regards. Max.
Re[8]: Исключения или коды возврата?
От: WPooh США  
Дата: 12.05.06 12:30
Оценка:
Здравствуйте, Max.Subpixel, Вы писали:

MS>Даже если три года не менять машину — такого старья быть не может...

MS>На такой машине Win 2000 работает очень с трудом....
А если посмотреть на год сообщения, то получим 2002-3=1999.
В общем, было такое старье. Trust me.
К этому моменту у меня внутри 0.5, 0.7, 0.33 (с) НС
Re[9]: Исключения или коды возврата?
От: Max.Subpixel Россия  
Дата: 12.05.06 12:37
Оценка:
Здравствуйте, WPooh, Вы писали:

WP>Здравствуйте, Max.Subpixel, Вы писали:


MS>>Даже если три года не менять машину — такого старья быть не может...

MS>>На такой машине Win 2000 работает очень с трудом....
WP>А если посмотреть на год сообщения, то получим 2002-3=1999.
WP>В общем, было такое старье. Trust me.



не заметил

ну правда я помню, что в 99 мы закупали в офис 433 целерон с 14Гб винтами и 17 дюймами мониторов...
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Best Regards. Max.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.