На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Обратите внимание:
1. Прежде чем начать новую тему или отправить сообщение, убедитесь, что вы не нарушаете правил форума!
2. Обязательно воспользуйтесь поиском. Возможно, Ваш вопрос уже обсуждали. Полезные ссылки приведены ниже.
3. Темы с просьбой выполнить какую-либо работу за автора в этом разделе не обсуждаются.
4. Используйте теги [ code=cpp ] ...текст программы... [ /code ] для выделения текста программы подсветкой.
5. Помните, здесь телепатов нет. Старайтесь формулировать свой вопрос максимально грамотно и чётко: Как правильно задавать вопросы
6. Запрещено отвечать в темы месячной и более давности без веских на то причин.

Полезные ссылки:
user posted image FAQ Сайта (C++) user posted image FAQ Форума user posted image Наши Исходники user posted image Поиск по Разделу user posted image MSDN Library Online (Windows Driver Kit) user posted image Google

Ваше мнение о модераторах: user posted image B.V.
Модераторы: B.V.
Страницы: (3) 1 [2] 3  все  ( Перейти к последнему сообщению )  
> Исключения С++,С и SEH-исключения
    Проверил с теми опциями котрые доступны в IDE. Исключения в Release версии ловятся только при полном отключении оптимизации.
      Цитата
      У тебя z не используется, поэтому компилятор наверняка выкинул код её вычисления.

      Да правильно, а я не догадался.
      Но почему тогда не выкидывает при
      ExpandedWrap disabled
                float x,y,z;
                x = 1.0;
                y = 0.0;
                z = x/y;
        Цитата Qraizer @
        Добавь volatile хотя бы.

        Если добавить volatile, то всё работает - ловит исключение. но всё же странно почему компилятор вырезает блоки try-catch типа с целью оптимизации!
          Та не блок он вырезал, а вычисление z. Кроме volatile от супероптимизации её вычисления его б остановило объявление z глобальной с внешним связыванием. Когда z локальная, её время жизни полностью под контролем оптимизатора, вот он и берёи на себя больше, чем в этом примере от него требуется.
          Dem_max, не знаю. Пути оптимизатора неисповедимы. Наверно не рискнул из-за закулисной жизни _matherr().
            Понятно, не врубился сразу. С глобальными тоже работает. Про деструкторы по ссылке пока ещё почитаю.

            Qraizer вы как считаете использовать лучше try-catch и /EHa или же __try/__except для того чтобы надёжно ловить все исключения(от системы, не программные throw)?
            Сообщение отредактировано: neokoder -
              По try/catch ты не получишь подробной информации о проблеме, если не воспользуешься какой-нибудь прослойкой в лице хотя бы той же _set_se_translator(). Если тебя не интересует эта информация, а интересует только безопасный код, не допускающий утечек ресурсов из-за проблем не в твоём коде, то это не проблема.
              По __try/__except ты не получишь информации о C++-проблеме вообще никак, ибо кухня С++ exception handling вообще не стандартизирована и не документирована в отличие от SEH. Опять же это не проблема, если тебя интересует только безопасный код.
              Для безопасного кода достаточно RAII посредством пар "конструктор/деструктор" и ключика -EHa. Для получения информации о проблеме, если вдруг она-таки потребуется, для C++ достаточно класса для инкапсуляции SEH-контекста и _set_se_translator(). Для того же в случае C надёжного решения нет. Вывод: try/catch предпочтительнее.
              Однако в функциях, в чьих контексте нет объектов с нетривиальными деструкторами можно и __try/__except и/или __try/__finally, это будет чуть эффективнее. Но в случае появления в будущем в их констекте таких объектов придётся переписывать.
              Сообщение отредактировано: Qraizer -
                Цитата Qraizer @
                По try/except ты не получишь подробной информации о проблеме, если не воспользуешься какой-нибудь прослойкой в лице хотя бы той же _set_se_translator().

                Может вы имели ввиду try/catch?

                Цитата Qraizer @
                По __try/__except ты не получишь информации о C++-проблеме вообще никак, ибо кухня С++ exception handling вообще не стандартизирована и не документирована в отличие от SEH.

                А какие не мои собственные исключения С++(системные) могут привести к вылету из программы?

                Цитата Qraizer @
                Для безопасного кода достаточно RAII посредством пар "конструктор/деструктор" и ключика -EHa.

                Будьте добры, что такое RAII?

                Цитата Qraizer @
                Вывод: try/except предпочтительнее.

                Не понял здесь немного. Вы различаете __except и except? Я в MSDN нашёл информацию только об __except. Может вы имели ввиду try/catch?
                  Ну да, try/catch. Перекопипастил.
                  Поправил.

                  Добавлено
                  Цитата neokoder @
                  А какие не мои собственные исключения С++(системные) могут привести к вылету из программы?
                  "Не твои собственные", в смысле "не в твоём коде". Свой код ты можешь вылизать в абсолют, хотя бы теоретически. Но когда ты вызываешь не свой код, находящийся в библиотеке не твоего авторства к примеру, с ним ты ничего не сможешь поделать. (Конечно, наличие исключений отнюдь не означает наличие багов, это ещё и может означать плохое тобою чтение документации.)

                  Добавлено
                  Цитата neokoder @
                  Будьте добры, что такое RAII?
                  Resource Allocation Is Initialization. Идиома такая. Конструктор и только конструктор захватывает ресурс и объявляет экземпляр класса его владельцем. Деструктор и только деструктор его освобождает. Стандартом языка гарантируются вызовы деструкторов локальных объектов в любом случае, и при обычном завершении функции, и при размотке стека при исключении. Это позволяет резко сократить количество try-блоков в программе и при этом гарантировано не иметь утечек. Эта тема вот тут рассмотрена гораздо подробнее и с примерами.
                  Сообщение отредактировано: Qraizer -
                    Для себя решил. Использовать __try, __finally,__leave как наилучший вариант обработки исключительных ситуаций в своём коде. Примером может служить код функции из книги Рихтера:
                    ExpandedWrap disabled
                      DWORD Funcarama4()
                      {
                          // Внимание: инициализируйте все переменные, предполагая худшее
                          HANDLE hFile = INVALID_HANDLE_VALUE;
                          PVOID pvBuf = NULL;
                          
                          // предполагаем, что выполнение функции будет неудачным
                          BOOL bFunctionOk = FALSE;
                          __try
                          {
                              DWORD dwNumBytesRead;
                              BOOL bOk;
                              
                              hFile = CreateFile(TEXT("SOHEDATA.DAT"), GENERIC_READ,FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
                              if (hFile == INVALID_HANDLE_VALUE)
                              {
                                  __leave;
                              }
                              
                              pvBuf = VirtualAlloc(NULL,1024, MEM_COMMIT, PAGE_READWRITE);
                              if (pvBuf == NULL)
                              {
                                  __leave;
                              }
                              
                              bOk = ReadFile(hFile, pvBuf, 1024, &dwNumBytesRead, NULL);
                              if (!bOk || (dwNumBytesRead == 0))
                              {
                                  __leave;
                              }
                              
                              // что-то делаем с данными
                              //...
                              
                              // функция выполнена успешно
                              bFunctionOk = TRUE;
                          }
                          __finally
                          {
                              // очистка всех ресурсов
                              if (pvBuf != NULL)
                                  VirtualFree(pvBuf,1024,MEM_RELEASE|MEM_DECOMMIT);
                              if (hFile != INVALID_HANDLE_VALUE)
                                  CloseHandle(hFile);
                          }
                          
                          // продолжаем что-то делать
                          return(bFunctionOk);
                      }


                    Что касается вызова сторонних функций из библиотек, то для них буду использовать следующий принцип. Программу буду компилировать по умолчанию с ключом (/EHsc) или (/EHs) (в зависимости от задачи). Т.е я не буду ловить структурные исключения c помощью catch. Просто нет желания связываться с _set_se_translator, который необходимо определять для каждого потока, кроме того, если вызывается функция из dll, то она может создавать свой поток и я уже никак не смогу перехватить исключение в этом потоке. Если я не прав поправьте. Поэтому я решил просто использовать 2 функции для вызова стороннего кода- одну для обработки С++ исключений, а вторую для структурных. Т.е. выглядет это так:

                    ExpandedWrap disabled
                      //compile with (/EHsc)
                       
                      int x,y,z;
                      void SafeCall_1();
                       
                       
                      LONG ExceptFilter (DWORD except_code)
                      {
                          if (except_code==EXCEPTION_INT_DIVIDE_BY_ZERO)
                          {
                                      //здесь мы узнаём о произошедшем исключении
                              printf("EXCEPTION_INT_DIVIDE_BY_ZERO\n");
                              return EXCEPTION_EXECUTE_HANDLER;
                          }
                          else
                          {
                                      //здесь мы не обрабатываем те исключения которые система должна решить сама
                              printf("Uknown exception\n");
                              return EXCEPTION_CONTINUE_SEARCH;
                          }
                       
                      }  
                       
                      void UnknownFunction(int what)
                      {
                       
                              x = 1;
                              y = 0;
                              z = x/y;
                       
                          if (what==1)
                              throw (char *)"I am throw an exception";
                      }
                       
                      void SafeCall()
                      {
                        __try
                        {
                            SafeCall_1();
                        }
                        __except(ExceptFilter(GetExceptionCode()))
                        {
                       
                        }
                       
                        printf("We don't exit and can continue work\n");
                       
                      }
                       
                      void SafeCall_1()
                      {
                       
                       
                          try
                          {
                              UnknownFunction(2);
                          }
                          catch(char *mes)
                          {
                                      //здесь мы узнаём о произошедшем исключении
                              printf("Unknown function has raised an exception with message: %s\n",mes);
                          }
                          catch(...)
                          {
                                      //здесь мы узнаём о произошедшем исключении
                              printf("Unknown function has raised an unknown exception\n");
                          }
                       
                        
                      }
                      int _tmain(int argc, _TCHAR* argv[])
                      {
                       
                       SafeCall();
                       
                       
                       printf("Press any key to close the window...");
                       _getch();
                       return 0;
                      }


                    Был бы рад услышать ваши отклики и замечания. Особенно в плане того какие струтурные исключения нельзя ловить, а надо дать системе обработать их самой(т.е. это не означает вылета из программы). Вообще есть такие?
                    Сообщение отредактировано: neokoder -
                      neokoder, пример Рихтера попадает под упомянутое мною исключение. Она сугубо Сшная, так что Плюсовым try там делать нечего.
                      Цитата neokoder @
                      Что касается вызова сторонних функций из библиотек, то для них буду использовать следующий принцип. ...
                      Ну и правильно. Сам так делаю. Это иногда требует некоторой дополнительной ручной работы, но это оправдано. В Плюсовом коде SEH исключений либо нет, т.к. их вычищают, ибо это ошибки, их проще предотвратить проверкой параметров, чем сглаживать последствия от них, либо документированы, а значит не неожиданны, и легко хедлятся индивидуально по месту ещё на стадии программирования. Бывают, конечно, неприятности с багами в библиотеках, но для этого существуют багрепорты их авторам и временные их воркароунды в своём коде. Да и редки они обычно, если библиотека не левый какой-нибудь "компонент". А если нередки, то написать самому обычно дешевле выходит, хотя бы в плане нервов.

                      Добавлено
                      Цитата neokoder @
                      если вызывается функция из dll, то она может создавать свой поток и я уже никак не смогу перехватить исключение в этом потоке
                      Эти потоки тебя вообще-то и не касаются. Они вряд ли будут выполнять твой код. А если будут, то и проблемы уже нет, перехватывай.

                      Добавлено
                      Цитата neokoder @
                      какие струтурные исключения нельзя ловить, а надо дать системе обработать их самой(т.е. это не означает вылета из программы).
                      Классика. Не надо обрабатывать исключение, если ты не знаешь, что с ним делать. Отправляй дальше, там найдётся кому обработать. Всё, что тебе тут надо - откатиться к своим инвариантам. RAII тут как нельзя кстати - 0 строк кода за исключением кода деструкторов. Ну, или __finally, если это C. Посмотри по той ссылке пример с реализацией SS::operator=().
                      Сообщение отредактировано: Qraizer -
                        Цитата Qraizer @
                        neokoder, пример Рихтера попадает под упомянутое мнорю исключение. Она сугубо Сшная, так что Плюсовым try там делать нечего.

                        Да, а я в принципе С++ функциями редко пользуюсь, разве что классы свои делаю.
                        А для работы с С++ функциями, которые могут дать исключения тот же new я всегда буду заключать в блоки try...catch.

                        Добавлено
                        Цитата Qraizer @
                        Эти потоки тебя вообще-то и не касаются. Они вряд ли будут выполнять твой код. А если будут, то и проблемы уже нет, перехватывай.

                        Нет, ну как не касаются. Я вызвал функцию из сторонней dll , она создала поток, в потоке произошло исключение которое она не смогла обработать. Всё! Если я пользуюсь _set_se_translator перехватить это исключение я уже не смогу и программа завершится. Вот почему я не желаю пользоваться _set_se_translator. А с помощью 2-х функций такое исключение всегда поймается. Если не прав поправьте.

                        Добавлено
                        Цитата Qraizer @
                        Идиома такая. Конструктор и только конструктор захватывает ресурс и объявляет экземпляр класса его владельцем. Деструктор и только деструктор его освобождает. Стандартом языка гарантируются вызовы деструкторов локальных объектов в любом случае, и при обычном завершении функции, и при размотке стека при исключении.

                        Ну если честно, ничего не зная о RAII я так всегда и делал ;). Единственно я не знаю на 100% о следующем:
                        1) Будет ли гарантированно раскручиваться стек и вызываться деструкторы локальных объектов(классов в основном) после возникновения структурного(SEH) исключения?
                        2) Если да, то обязательно ли для этого использовать ключ компилятора (/EHa) или можно обойтись(/EHsc)?
                        Сообщение отредактировано: neokoder -
                          Цитата Qraizer @
                          Классика. Не надо обрабатывать исключение, если ты не знаешь, что с ним делать. Отправляй дальше, там найдётся кому обработать.

                          Так вот здесь конкретный вопрос. Какие исключения именно для моего кода(не стороннего) из нижеследующего списка мне необходимо принять с EXCEPTION_EXECUTE_HANDLER, и просто ничего не делать, главное чтобы программа продолжала работу, например случайное EXCEPTION_INT_DIVIDE_BY_ZERO, а какие исключения надо отдать системе с помощью EXCEPTION_CONTINUE_SEARCH, но при этом главное чтобы по возможности программа не завершилась, в крайнем случае только тогда, когда исключение ведёт к серьёзному нарушению в программе и её продолжение чревато последствиями. Пусть уж в этом случае создаёт минидамп и отправляет его Microsoft как обычно.

                          ExpandedWrap disabled
                            #define EXCEPTION_ACCESS_VIOLATION          STATUS_ACCESS_VIOLATION
                            #define EXCEPTION_DATATYPE_MISALIGNMENT     STATUS_DATATYPE_MISALIGNMENT
                            #define EXCEPTION_BREAKPOINT                STATUS_BREAKPOINT
                            #define EXCEPTION_SINGLE_STEP               STATUS_SINGLE_STEP
                            #define EXCEPTION_ARRAY_BOUNDS_EXCEEDED     STATUS_ARRAY_BOUNDS_EXCEEDED
                            #define EXCEPTION_FLT_DENORMAL_OPERAND      STATUS_FLOAT_DENORMAL_OPERAND
                            #define EXCEPTION_FLT_DIVIDE_BY_ZERO        STATUS_FLOAT_DIVIDE_BY_ZERO
                            #define EXCEPTION_FLT_INEXACT_RESULT        STATUS_FLOAT_INEXACT_RESULT
                            #define EXCEPTION_FLT_INVALID_OPERATION     STATUS_FLOAT_INVALID_OPERATION
                            #define EXCEPTION_FLT_OVERFLOW              STATUS_FLOAT_OVERFLOW
                            #define EXCEPTION_FLT_STACK_CHECK           STATUS_FLOAT_STACK_CHECK
                            #define EXCEPTION_FLT_UNDERFLOW             STATUS_FLOAT_UNDERFLOW
                            #define EXCEPTION_INT_DIVIDE_BY_ZERO        STATUS_INTEGER_DIVIDE_BY_ZERO
                            #define EXCEPTION_INT_OVERFLOW              STATUS_INTEGER_OVERFLOW
                            #define EXCEPTION_PRIV_INSTRUCTION          STATUS_PRIVILEGED_INSTRUCTION
                            #define EXCEPTION_IN_PAGE_ERROR             STATUS_IN_PAGE_ERROR
                            #define EXCEPTION_ILLEGAL_INSTRUCTION       STATUS_ILLEGAL_INSTRUCTION
                            #define EXCEPTION_NONCONTINUABLE_EXCEPTION  STATUS_NONCONTINUABLE_EXCEPTION
                            #define EXCEPTION_STACK_OVERFLOW            STATUS_STACK_OVERFLOW
                            #define EXCEPTION_INVALID_DISPOSITION       STATUS_INVALID_DISPOSITION
                            #define EXCEPTION_GUARD_PAGE                STATUS_GUARD_PAGE_VIOLATION
                            #define EXCEPTION_INVALID_HANDLE            STATUS_INVALID_HANDLE
                            #define EXCEPTION_POSSIBLE_DEADLOCK         STATUS_POSSIBLE_DEADLOCK
                          Сообщение отредактировано: neokoder -
                            Цитата neokoder @
                            Для себя решил. Использовать __try, __finally,__leave как наилучший вариант обработки исключительных ситуаций в своём коде. Примером может служить код функции из книги Рихтера:

                            А по моему это уже перебор.
                            т.е. этот пример демонстрирует приём работы с __try, __leave, __finally
                            но по сути здесь нет исключений.
                            Гораздо удобнее использовать классы-обьекты содержащие
                            CreateFile, VirtualAlloc, ReadFile и.т.п. и высвобождающие
                            ресурсы в деструкторе. В том случае, если это не удобно
                            делать соотв. методом.
                              Цитата ЫукпШ @
                              А по моему это уже перебор.
                              т.е. этот пример демонстрирует приём работы с __try, __leave, __finally
                              но по сути здесь нет исключений.

                              Ну естественно исключений нет, но появится могут в "любой момент" ;), для того __finally и нужен, чтобы корректно освободить реурсы.

                              Цитата ЫукпШ @
                              Гораздо удобнее использовать классы-обьекты содержащие
                              CreateFile, VirtualAlloc, ReadFile и.т.п. и высвобождающие
                              ресурсы в деструкторе. В том случае, если это не удобно
                              делать соотв. методом.

                              Ну а вообще, кому что удобнее.

                              ЫукпШ, вы по более важным(для меня) вопросам в моих последних 2-х постах можете что-то сказать?
                              Сообщение отредактировано: neokoder -
                                Цитата neokoder @
                                ЫукпШ, вы по более важным(для меня) вопросам в моих последних 2-х постах можете что-то сказать?

                                А я то как раз и ответил на самый важный, на мой взгляд, вопрос.
                                В вышеупомянутом примере имеет место явная попытка скрестить
                                ужа с ежом. Что не нужно.
                                Пусть высвобождением ресурсов занимаются обьекты, а блоки
                                try/canth ловят и обрабатывают исключения. Одно другому
                                не мешает.

                                Добавлено
                                Цитата neokoder @
                                1) Будет ли гарантированно раскручиваться стек и вызываться деструкторы локальных объектов(классов в основном) после

                                Да, и информацию об этом легко найти в Сети. тут, например
                                И в книгах, конечно.

                                Добавлено
                                Цитата neokoder @
                                Так вот здесь конкретный вопрос. Какие исключения именно для моего кода(не стороннего) из нижеследующего списка мне необходимо принять с EXCEPTION_EXECUTE_HANDLER, и просто ничего не делать, главное чтобы программа продолжала работу, например случайное EXCEPTION_INT_DIVIDE_BY_ZERO, а какие исключения надо отдать системе с помощью EXCEPTION_CONTINUE_SEARCH,

                                Об этом может знать только автор конкретной программы -
                                как она должна вести себя в этих случаях.
                                Что касается "отдавать системе", то система завершит
                                аппликэйшын стандартным мессэдж-боксом. На мой взгляд,
                                в необходимом случае лучше показать свой собственный.
                                Сообщение отредактировано: ЫукпШ -
                                1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
                                0 пользователей:
                                Страницы: (3) 1 [2] 3  все


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0571 ]   [ 15 queries used ]   [ Generated: 18.07.25, 04:08 GMT ]