На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: Qraizer, Hsilgos
  
> Кто берет ответственность за try? , в разных ОСях?
    В стандарте C++ есть такой оператор:
    try
    {
    }
    catch()
    {
    }

    очень хороший оператор.
    Внимание: вопрос.

    Кем определяется поведение при выполнении данного оператора? Т.е. - это наверное
    зависит от операционной системы?
    Вычитал недавно в одной умной книжке, что "в NT обработка исключений заложена на
    уровне ядра". Что означает сия фраза? Значит, если я в 9x использую оператор, то
    у меня ничего не выгорит? А в UNIX-ах?
    Если это сделано на уровне ядра, то наверное при входе в подобный блок
    создается какой то объект ядра, который.. ну и так далее?
    Если нет, то тогда как?

    Отдалимся от теории, и зададим практический вопрос.
    Если это НЕ объект ядра, то что делает процессор при наличае нескольких крит. секций?
    Ну например:
    у меня есть несколько потоковых функций, которые заключены в
    try - catch. Потоковые функции выполняются долго, практически вечно.
    Может ли в ОСи существовать несколько подобных блоков (интересует наблюдения
    не только в NT-шных, но и других осях - особливо 9x, ну и до кучи - *nix-ы).
    Сообщение отредактировано: AQL -
      мне тоже охота порассуждать на эту тему :)

      Я всегда (когда подучился) предпологал что есть функции, операции, которые выбрасывают исключения, если нет catch то это как выброс из функции все выше и выше, без всяких ретурнов. Но первый catch который ловит данное исключение остановит подобный moveback. Никакое ядро за это не отвечает. Если я вычитаю два double сам (с занулением), то могу вызвать исключение могу на него забить.
        а как тогда насчет вот такого:

        Цитата

        "в NT обработка исключений заложена на уровне ядра"


        то есть, они готовы ловить исключения, которые предусмотренны? То есть
        если CFileException или CMemoryException от MFC - NT готова поймать,
        а если что то свое?
        (ну, напишу я в throw просто вот так вот: throw(char *){return MY_EXCEPTION_OCCURED;} )
        - то NT ловить его не будут? Тогда это не есть хорошо.
        А в чем будут различая на 9x? Моя что то совсем понимать перестала.

        Да, и по поводу количества открытых try()-ев вопрос открыт до сих пор. В доке
        я ничего подобного не нашел. Сказано - что "можно критические
        штюки заключать в try" . А когда нельзя заключать ( и почему!) -- ничего не сказано.
          Для начала надо определиться. Есть исключения, специфицированные стандартом C++ (try/catch). За их поддержку отвечает CRTL. Но в операционных системах могут быть свои механизмы генерации и обработки исключительных ситуаций. В Win32 - это так называемый SEH (Structured Exception Handling), в *NIX - это сигналы. Ну и т. д. По идее (и в общем случае), механизмы, заложенные в операционные системы никакого отношения к C++-исключениям не имеют. В случае с NT многие исключения ОС превращаются в программные исключения все той-же CRTL и их можно ловить на три точки (catch(...)), но лучше - через блоки __try/__except, т. к. в этом случае можно получить доп. информацию об исключении.
            то есть - ответственность берет CRTL? Хорошо.
            Если exception-а не случается, то CRTL вообще забивает болт на это дело?
            Мне все таки интересно узнать, как уживаются несколько исключений.
            Сообщение отредактировано: AQL -
              Цитата
              AQL, 29.01.04, 12:04
              Если exception-а не случается, то CRTL вообще забивает болт на это дело?

              В смысле? Ты можешь сгенерировать исключение сам (с использованием throw).
                хм. сам - это хорошо.
                В общем - идея такая. Нужно как бы подстраховаться. Всю функцию потока
                я хочу обнести одним большим try() - потому что мало ли чего.
                При этом если случается какая либо беда - не важно какая (она может случиться
                где угодно и когда угодно - конкретизировать место я не хочу)
                было сгенерировано исключение, при этом поток должен КОРРЕКТНО завершить
                свою работу, и отослать ответсвенному лицу (мне то есть) письмецо:
                "обратите внимание на логи, котоые сделал поток такой то, потому что
                там произошла какая то беда". При этом остальные потоки должны продолжать
                работать. Корректно ли заключить всю функцию потока в один большой try()?
                Так как потоков будет много - то получиться несколько try секций.
                Они уживутся?
                Сообщение отредактировано: AQL -
                  работу корректо завершать на мой взгляд надо не в catch а в finally

                  если ты функцию потока обнесешь try то ты же из неё уже вывалишся !? для корректности надо ловить ошибки в том месте где они появляются.
                    ? какая жаль. А я хотел все устроить как можно проще.. ладно, придется подумать
                    и погемороиться. Вся беда в том, что мне в общем то не интересно, что за исключение
                    произошло. Мне важно то, что оно произошло. А уж что там происходило - я в логах
                    посмотрю.
                    Сообщение отредактировано: AQL -
                      AQL, не все так плохо
                      ExpandedWrap disabled
                         
                        try
                        {
                        // что-то делаешь
                        }
                        catch (...)
                        {
                        // посылаешь письмо
                        }

                      в функции потока тебе поможет :))

                      Sazabis, во-первых, finaly в C++ нет и (я думаю) не будет. Во-вторых, вместо этого есть замечательная парадигма "объявление есть инициализация", в соответствии с которой выделение ресурсов должно быть в конструкторе соотв. класса, а разрушение - в деструкторе. Тогда никакой try-catch тебе не страшен, т. к. гарантируется, что в процессе раскрутки стека вызываются деструкторы всех локальных объектов.
                        О! Именно это я и хотел услышать. Супер. Я то уж стал было думать, что
                        придется сдецл погемороиться. Я чувствовал, что такое должно прокатить!
                          Цитата
                          AQL, 29.01.04, 12:53
                          О! Именно это я и хотел услышать. Супер. Я то уж стал было думать, что
                          придется сдецл погемороиться. Я чувствовал, что такое должно прокатить!

                          Но должен тебя предупредить - это считается плохим стилем.
                            :( - так - а где же плачущий смайлик?
                              прошу обратить внимание на __finally а не finaly

                              в подобных вариантах

                              ExpandedWrap disabled
                                FILE *fn;
                                 
                                try{
                                  fn = fopen(...;
                                  
                                 
                                } __finally{
                                  fclose( fn );
                                }


                              или

                              ExpandedWrap disabled
                                cMyClass *mc = new cMyClass;
                                 
                                try{
                                  if( func( mc ) == (any) )return true;
                                 
                                  for( ... )if( ... )return ...
                                } __finally{
                                  delete mc;
                                }
                                return false;


                              можно конечно и return delete mc, true;
                              или cMyClass mc; func( &mc ); но это как пример я написал.
                                __finaly (как явствует из MSDN) - C и C++ расширение от Microsoft. Сделано специально для обработки SEH-исключений. В частности:
                                Цитата

                                Note Structured exception handling works with Win32 for both C and C++ source files. However, it is not specifically designed for C++. You can ensure that your code is more portable by using C++ exception handling. Also, C++ exception handling is more flexible, in that it can handle exceptions of any type. For C++ programs, it is recommended that you use the new C++ exception-handling mechanism (See try, catch, and throw statements).

                                Таким образом, не изветсно - как он поведет себя с деструкторами и т. п. А твой пример легко приводится вот к такому виду:
                                ExpandedWrap disabled
                                   
                                  try
                                  {
                                  std::ifstream file(...);
                                  }
                                  catch (...) {;}

                                и
                                ExpandedWrap disabled
                                   
                                  std::auto_ptr<cMyClass> mc(new cMyClass(...));
                                  try
                                  {
                                    if( func( mc ) == (any) )return true;
                                   
                                    for( ... )if( ... )return ...
                                  }
                                   
                                  return false;

                                и никакой головной боли.
                                  я так и думал что 2 пример слишком абстрактный :) и для него найдется куча решений, как и для первого впрочем. Я хотел сказать что в блок __finally мы попадем до выхода из блока try и там можно сделать все что необходимо для корректного завершения блока try

                                  ExpandedWrap disabled
                                    //для файла который мы открыли:
                                    try{
                                      if( ReadHeader( fn ) != "Rar!" )return; //файл не закрываем!, исключений нет
                                      anyobject = ReadLine( 10 ); // допустим выбрасывает исключение
                                    } catch (...) {;}
                                    Цитата
                                    Sazabis, 29.01.04, 14:36

                                    //для файла который мы открыли:
                                    try{
                                    if( ReadHeader( fn ) != "Rar!" )return; //файл не закрываем!, исключений нет
                                    anyobject = ReadLine( 10 ); // допустим выбрасывает исключение
                                    } catch (...) {;}


                                    Если файл был открыт до блока try, то мы его можем спокойно закрыть после блока catch. __finaly тут ни к чему.
                                      я имею ввиду множественные выходы из функции. Тот же пример, после открытия файла, проверить его заголовок, свои там данные или не те. После открытия мы можем выйти как после того, как убедимся что файл не пригоден для дальнейшего чтения, так и после успешного считывания файла. В обоих случаях файл надо закрыть. Сразу предвижу ответ if( ReadHeader( fn ) != "Rar!" )throw ...; но если на выход надо скажем значение enum подавать то с catch это уже switch'и и гемор.
                                        Так, давай еще раз, по-порядку. При программировании на C++ правильной парадигмой считается парадигма "объявление ресурса есть инициализиация". Что это значит. Если ты объявляешь объект (например, ifstream), то выделение ресурсов для этого объекта производится в конструкторе (в общем случае), а деинициализация ресурсов - в деструкторе. Следуя этой парадигме мы получаем код, для которого блок __finaly не нужен, т. к. при выходе из области видимости переменной (выделенного ресурса) автоматически вызывается деструктор и производится деинициализация. Это справедливо равно как для выхода из метода, так и для выхода из блока try или любого другого фрагмента, ограниченного операторными скобками ({}). Таким образом, опасности блока __finaly заключается в следующем:
                                        1. Это не стандартная языковая конструкция. Таким образом, код получается непереносимым и не естественным для языка.
                                        2. Нет гарантии, что эта конструкция реализована правильно с точки зрения именно C++. Т. е. что производится корректное разрушение всех локальных объектов и т. п, т. к. корнями она уходит в С (от Microsoft).
                                        3. Использование этой конструкции имеет ряд ограничений. В частности, нельзя одновременно (в одном методе) использовать конструкции try/catch и try/__except/__finaly
                                        4. Использование этой конструкции противоречит идеалогии языка (см. первый абзац), и прививает плохой стиль.

                                        Приведенные тобою примеры с файлом не состоятельны по простой причне - если пользоваться std::ifstream или CFile, то необходимость блока __finaly отпадает сама собой, т. к. все необходимые действия по закрытия файла будут выполнены в деструкторах соответствующих классах. Вариант с FILE я не рассматриваю, т. к. это характерно для программирования на C, а не на С++.
                                          Цитата

                                          Но должен тебя предупредить - это считается плохим стилем


                                          А кстати, почему? если есть такая возможность в языке, то наверное, можно
                                          ее использовать. Дело в том, что я отлавливаю все ошибки руками, проверяю HRESULT-ы
                                          указатели на 0, ну и т.д., try я хочу использовать как верхний уровень безопасности,
                                          что ли. потому что бывает то всякое.
                                            Цитата
                                            AQL, 29.01.04, 15:49
                                            А кстати, почему?

                                            Потому что если все ошибки правильно обрабатываются, а вероятность SEH нулевая (т. е. нет ситуаций, которые моглибы привести, например, к AV), то catch (...) не нужен. Минус его еще в том, что он скрывает истинное место возникновения ошибки. Т. е. если у тебя есть catch (...) и (даже под дебагером) возникает, например, AV, то даже дебагер его не поймает.
                                              ну, это я по логам разберу, докудова исполнение дошло.
                                                Цитата
                                                AQL, 29.01.04, 12:49
                                                если есть такая возможность в языке, то наверное, можно
                                                ее использовать


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

                                                А как реализованно try/catch зависит от компилятора. Делфи например вызывает RaiseException из kernel32. Есть подозрение, что Builder может делать то же самое.
                                                  у меня как раз и возник вопрос по мотивам Билдера. Вроде в в исходниках были
                                                  try и catch, только все равно, когда драйвер устройства вставал криво -
                                                  типичное красное окошечко и все умирало. Мне показалось, что это не очень логично.
                                                  0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                                  0 пользователей:


                                                  Рейтинг@Mail.ru
                                                  [ Script execution time: 0,0479 ]   [ 16 queries used ]   [ Generated: 3.05.24, 08:18 GMT ]