какой код лучше, с TRY-CATCH или без?

Тема в разделе "WASM.BEGINNERS", создана пользователем verelex, 3 ноя 2009.

  1. varnie

    varnie New Member

    Публикаций:
    0
    Регистрация:
    2 янв 2005
    Сообщения:
    1.785
    по стандарту - обязано кидать std::bad_alloc.
    хотя можно написать так:
    Код (Text):
    1. Foo* pFoo = new (std::nothrow) Foo;
    2.  if (pFoo) {
    3.    //
    4.  }
    и тогда будет возвращаться нуль в случае неудачи вместо кидания ексепшна.
    если память не изменяет, не кидает экспешна, а возвращает нуль в случае неудачи.
     
  2. J0E

    J0E New Member

    Публикаций:
    0
    Регистрация:
    28 июл 2008
    Сообщения:
    621
    Адрес:
    Panama
    operator new ВСЕГДА возвращает не нулевой адрес, проверка лишяя. Ты наверное хотел написать new (std::nothrow)
     
  3. varnie

    varnie New Member

    Публикаций:
    0
    Регистрация:
    2 янв 2005
    Сообщения:
    1.785
    упс, нечайно нажал ентер,пардон)

    в пред. моём сообщении последняя строчка должна звучать так:
    поправка
    если память не изменяет, VC6 не кидает экспешна, а возвращает нуль в случае неудачи.
     
  4. spa

    spa Active Member

    Публикаций:
    0
    Регистрация:
    9 мар 2005
    Сообщения:
    2.240
    вы еще XJ-1 вспомните
     
  5. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    На VC6 исключения вообще опасны. Ещё они имеют подводные камни, лучше не злоупотреблять. Если можно обойтись - лучше обойтись.
     
  6. punxer

    punxer Андрей

    Публикаций:
    0
    Регистрация:
    16 окт 2006
    Сообщения:
    1.327
    Адрес:
    Ржев
    Если уверены всебе и уверены что отловите сами все возможные ситуации, то вперёд, без try catch не обойтись во многих случаях. Программа вызывает во много раз больше чужого кода чем сама есть. ИМХО try и проверки. Ни как иначе.
     
  7. AsmGuru62

    AsmGuru62 Member

    Публикаций:
    0
    Регистрация:
    12 сен 2002
    Сообщения:
    689
    Адрес:
    Toronto
    Когда код пишется в стиле try/catch - неясна причина "падения" кода. Или надо делать отдельный класс исключения для каждой ошибки!

    Попался мне как-то проект (сделан в году этак 1994-м), где каждая процедура сделана в таком вот стиле:
    Код (Text):
    1. void foo (... parameters ...)
    2. {
    3.     open file ();
    4.     if (file not found) return;
    5.  
    6.     read file size ();
    7.     if (size == 0) return;
    8.  
    9.     allocate file buffer ();
    10.     if (buffer == NULL) return;
    11.  
    12.     load file ();
    13.     if (I/O errors while reading) return;
    14.  
    15.     check file format ();
    16.     if (bad format) return;
    17.  
    18.     parse file ();
    19.     if (parsing error found) return;
    20.  
    21.     close file
    22.     free memory
    23.     etc.
    24. }
    Естественно, после пары часов работы программа падает - при возврате из середины функций память и ресурсы утекают с пугающей быстротой. Это я к чему: стремление проверить каждый код возврата привело вот к такому эффекту.

    А вот как можно сделать код, который будет более читаемым и более поддерживаемым:
    Код (Text):
    1. #define BEGIN_SECTION(true_expression)  while(true_expression){
    2. #define END_SECTION     break;}
    3. #define CHECK(expr)     if (!(expr)) break
    4.  
    5. void LoadFile (...parameters...)
    6. {
    7.     //
    8.     // Initialize all resource handles to their
    9.     // invalid values
    10.     //
    11.     HFILE hfile = NULL;
    12.     PBYTE buf = NULL;
    13.     DWORD filesize = 0;
    14.  
    15.     BEGIN_SECTION (if parameters valid)
    16.         CHECK ((hfile = open file) != NULL);
    17.         CHECK ((filesize = get file size) != 0);
    18.         CHECK ((buf = malloc...) != NULL);
    19.         CHECK (no I/O errors while reading);
    20.         CHECK (file is not corrupted);
    21.         // etc.
    22.     END_SECTION
    23.     //
    24.     // Free resources, if allocated
    25.     //
    26.     if (file != NULL) close it;
    27.     if (buf != NULL) free it;
    28. }
    Достоинства очевидны:
    1. Читается великолепно - линейный код
    2. Натуральное место возврата из процедуры
    3. Ресурсы все освобождены - легко добавить ресурс и удалить если надо.
    4. Если сделать код возврата из каждого CHECK макро - всегда знаем, почему "упала" процедура.

    Недостаток: компилятор почему-то всегда (даже в RELEASE) генерирует forward jump для перехода на следующее CHECK макро - не оптимально в смысле скорости выполнения.
     
  8. Asterix

    Asterix New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2003
    Сообщения:
    3.576
    AsmGuru62
    не уловил связи проверок и утечками памяти
     
  9. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    Asterix
    если буфер выделен, а при I/O errors while reading или bad format или parsing error found мы return, а буфер не освобождаем
     
  10. BaGiE

    BaGiE New Member

    Публикаций:
    0
    Регистрация:
    27 мар 2005
    Сообщения:
    84
    Адрес:
    Mordor
    try-finally помогает)
     
  11. cupuyc

    cupuyc New Member

    Публикаций:
    0
    Регистрация:
    2 апр 2009
    Сообщения:
    763
    на мой субъективный взгляд нужно рассуждать примерно так. чтобы быстродействие было максимальным нужно в первую очередь думать о штатном режиме работы проги.
    например, идёт создание объекта файл:
    Код (Text):
    1. CFile *p_file = new CFile("1.tx*);
    можно сделать флаг, типа
    Код (Text):
    1. if (!p_file->is_success()) return;
    а можно в конструкторе генировать исключение и весь блок (если создаётся куча объектов) заключить в try.
    в первом случае нужно проверять - создался ли каждый объект в отдельности. если объектов сотня - сотня ифов, если тысяча - тысяча ифов. с другой стороны - как часто файлы не открываются? наверное, один на миллион - тогда зачем каждый раз проверять? вот и получается, что если заключить всё это в try - то в штатном режиме работы проги быстродействие будет выше.
    это мой
    взгляд.
     
  12. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    while(0)/break помогает.
     
  13. o14189

    o14189 New Member

    Публикаций:
    0
    Регистрация:
    19 июл 2009
    Сообщения:
    320
    +1
     
  14. J0E

    J0E New Member

    Публикаций:
    0
    Регистрация:
    28 июл 2008
    Сообщения:
    621
    Адрес:
    Panama
    while(0) конечно лучше читается чем DSL с BEGIN_SECTION, но обычно в С++ используют RAII и забывают про такие ошибки раз и навсегда ;)

    отсюда правило не использовать catch(...)
    а коды разные не надо делать? а что мешает эти коды в одном классе ошибки хранить? :)
     
  15. SadKo

    SadKo Владимир Садовников

    Публикаций:
    8
    Регистрация:
    4 июн 2007
    Сообщения:
    1.610
    Адрес:
    г. Санкт-Петербург
    http://sadko.xskernel.org/archives/1580 - немного поразмышлял об опасности исключений.
     
  16. J0E

    J0E New Member

    Публикаций:
    0
    Регистрация:
    28 июл 2008
    Сообщения:
    621
    Адрес:
    Panama
    Хорошая статья, но имеется маленькая ошибка в начальном условии
    как бы предполагается, что код будет писать малограмотный человек, не читающий описания вызываемых функций.

    Правильный вариант должен быть таким:

    void g() throw(e)

    или по Александреску:

    void g() // throw(e)
     
  17. SadKo

    SadKo Владимир Садовников

    Публикаций:
    8
    Регистрация:
    4 июн 2007
    Сообщения:
    1.610
    Адрес:
    г. Санкт-Петербург
    Имеется в виду именно тот случай, когда код пишется до того, как в g() поместят нечто, способное генерировать исключения.
     
  18. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    Все хорошо в меру, имхо. Лично использую и try/catch, и try/finally, и do while(0)/break. Даже не считаю зазорным поставить goto в месте, где оно действительно нужно :P
     
  19. spa

    spa Active Member

    Публикаций:
    0
    Регистрация:
    9 мар 2005
    Сообщения:
    2.240
    Great
    истина
     
  20. J0E

    J0E New Member

    Публикаций:
    0
    Регистрация:
    28 июл 2008
    Сообщения:
    621
    Адрес:
    Panama
    Значит ошибка в начальном условии - плохой архитектор. В любом случае, современные средства рефакторинга позволяют посмотреть дерево вызовов и проверить, если никто не удосужился написать тесты.

    Да, если оно сидит где-то в отлаженном коде в который без просу никто не лезет, то не получится ситуации как выше :)