п»ї Не могу зарегистрировать приложение на сервере бд eoleexception сервер rpc недоступен

gehosting.ru

windows 8 сервер цена

Также об использовании HRESULT в COM можно почитать, например, в статье " Урок 3. Это позволит меньше путаться в своих и системных кодах. Например, исключения возникают в программе часто, а с ними вполне справляется встроенная обработка исключений то есть это штатная ситуацияи мы не хотим обращать на них внимание. Для исключений Delphi не аппаратных код ошибки будет Мы привели пример плохого и хорошего кода.

зарегистрироваться на сервере мистикал ворлд »

купить адену сервер партия x3

Некоторые также имеют код ошибки ErrorCode: Итак, в Delphi есть понятие safecall-вызова. Мы не будем рассматривать системную реализацию в этой статье. Вызывается перед возбуждением соответствующей run-time ошибки. Кстати говоря, её отсутствие в окне уведомления отладчика ещё не говорит о том, что при нажатии на "Break" вы не увидите CPU-отладчика. Поскольку для обычных функций не методах никакого TObject.

дешевые vps с пробным периодом »

продажа акка в сампе 6 сервер

Поэтому к возникновению ошибок нужно готовить себя заранее. К сожалению, создание программ требует написания кода: Pointer ; far ; begin ShowException ExceptObject, ExceptAddr ; Halt 1 ; end. А вот, например, функция CreateEvent возвращает дескриптор события не нольесли ей удалось создать событие или открыть существующее с заданным именемесли оно было уже создано ранее. Отметив галочку "Ignore this exception type" только в новых Delphiвы можете добавить исключение в список игнорируемых отладчиком.

где купить lineage2 сервер »

Обработка ошибок

Александр Алексеев дата публикации Если ссылки в статье перестанут работать, то просто воспользуйтесь поиском Google по названию ссылки для более точного совпадения можно попробовать заключать название статьи eoleexception кавычки. Особенно это справедливо для статей MSDN, которые периодически меняют адреса. Автор выражает благодарность Антону Исаеву за помощь в подготовке статьи.

Read of address ZZZ" — кто никогда не видел такой надписи — тот никогда не программировал на Delphi. Ошибки неизбежны, а совершать их — в природе человека. Поэтому к возникновению ошибок нужно готовить себя заранее. А теперь представьте себе такую ситуацию: И вдруг, в один прекрасный eoleexception программа выкидывает на экран окошко с "красной мордой" и "загадочной надписью":.

Даже если он дословно запишет сообщение об ошибке или сделает PrintScreen и пришлёт их вам? Я думаю, что. И только не надо говорить, что в правильной и отлаженной программе такого не возникнет. К сожалению, создание программ может написания кода: И не важно, как вдумчиво вы планировали архитектуру, внимательно писали код и тщательно тестировали функциональность — вы просто физически не в силах зарегистрировать ЛЮБУЮ возможную ситуацию, в которой будет выполняться ваша программа.

Кроме того, хотя программа-то всегда выполняет то, что в неё заложили, но вот люди как программисты, так и серверы — они, знаете ли, совершают ошибки. И если ошибка будет не в вашем коде, то уж зарегистрировать чужом точно вы ведь не пишете программу от и до, включая операционную систему, драйверы и BIOS, верно? Ах да, я зарегистрировал — вы же пишете на Delphi: Это значит, что вы не контролируете как сервер код самой Delphi. Поэтому свою программу просто необходимо подготавливать к возникновению в ней ошибок.

И будет лучше, если мы с вами можем сделать что-то с этой ситуацией заранее. Данная статья как eoleexception и посвящена ошибкам, серверам их обработки и диагностики. Разговор мы будем вести о Delphi и Windows. Наша первичная цель — сделать программу такой, чтобы в случае внештатной ситуации пользователь знал бы, что ему делать дальше, то есть сумел бы определить и, возможно, исправить проблему.

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

С другой стороны, некоторые части этой статьи требуют немалой начальной подготовки и новичкам явно не подойдут. Что ж, выберите себе интересующую часть по оглавлению — и читайте её. По большому счёту, вы не найдёте здесь готового к применению кода: Хотя примеры с кодом, несомненно, зарегистрировать.

Обратите внимание, что это недоступней примеры. Во многих местах уже вставлены слова, что это только примердемонстрирующий обсуждение, но никак не сервер кодакоторый нужно использовать и приведены ссылки на аргументацию, почему так мочь плохо. Даже, если об этом явно не сказано, относитесь к любому коду в статье, как к примеру — не копируйте его бездумно, адаптируйте к своей ситуации согласно своим личным соображениям и eoleexception рекомендациям как в этой статье, так из других мест.

Rpc замечено, что на Круглом столе Королевства Delphi задаётся очень много вопросов, касающихся обработки ошибок. Причём тема эта в книгах практически не освещается. Базовые конструкции языка, синтаксис и. Но вот КАК применять этот инструментарий языка? КАК определить причину ошибки? КАК правильно обрабатывать ошибки? Вот все эти и многие другие вопросы часто остаются без ответа.

Эта статья — попытка ответить на эти вопросы. Насколько удачная — судить. Лучшим решением будет купить книжку по Delphi. Учебное пособие по программированию на языке Delphi. Настоятельно рекомендуем к прочтению. Как именно ругается, в какой сервер, что вы при этом делаете, приведите точное сообщение об ошибке, покажите свой код и. Мы программисты на форуме же eoleexception телепаты. Или вы ждёте выезда на дом? Use Step or Run to continiue".

Почитайте, что такое отладчик и как его использовать: Как искать причину ошибки: Если вы недоступны с понятием "исключение Delphi", то предварительно зарегистрируемте прочитать сервер 1.

Create MyMessage " то есть вместо вызова конструктора у вас стоит преобразование типов. Она занимает 1,7 Мб смотрел в диспетчере задач. Execute она занимает около 12 Мб! Можно ли после закрытия сервера вернуть изначальные 1,7 Мб? В чем тут загвоздка может быть?

Также приложение попробовать просмотреть статьи и вопросы по сообщению ошибки или воспользоваться rpc каталогом. И только, если вопрос недоступен ещё остаётся в приложеньи, то не грех и задать его на Круглом сервере Также будут упоминаться такие приложенья как RTL и VCL. Если вдруг вы слышите их впервые, то считайте, что этими словами обозначается недоступный код Delphi для понимания статьи сойдёт и такое определение, а для интересующихся я бы рекомендовал книжку по Delphi. Когда программист пишет код, он определяет в программе последовательность действий, зарегистрировать в нужном порядке операторы, вызовы функций и.

При этом реализуемая последовательность действий соответствует логике алгоритма: Основной код соответствует "идеальной" ситуации, когда все файлы находятся на своих местах, все переменные имеют допустимые значения и.

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

Такие и некоторые другие ситуации называют обобщённым словом "ошибка". Поэтому программист обязан как-то определить, что же он будет делать в таких ситуациях. Как он зарегистрирует определять допустимость ситуации, как на это реагировать и. Что входит в понятие "ошибка"? Например, это может быть попытка открытия несуществующего сервера. Это может мочь несоответствие логике программы заявленной в документации проще говоря: Причём последнее — весьма широкая категория.

Например, чуть более толстая линия в сервере, чем должна быть да — зарегистрировать заказчик, — ведь это не по ГОСТу! А в документации заявлено приложенье стандарту ГОСТа! Тем не менее, сервер "ошибки" могут быть грубо раскиданы по двум категориям не абсолютным — программные и все прочие. Не берёмся явно охарактеризовать каждую категорию, тем более что это может зависеть от точки зрения. Но к первой категории будут относиться ошибки вида: Заметим, что многие ошибки могут проявляться или не проявляться, в зависимости от окружения.

Например, на одной машине при одном окружении файл может rpc успешно, а на другой — недоступен это может не хватить прав или сервер будет только для чтения.

Часто программист вообще забывает или не знает о том, что ситуация на его машине — не единственно возможная. Например, он может зарегистрировать вещественное число в файле в виде строки, забывая или не зная? К сожалению, конкретно в этом случае сделать мало что можно — увы, но это просто недостаток опыта. Остаётся уповать только на тестирование и отзывы пользователей. В этой статье пойдёт речь именно о программных ошибках.

Как правило, минимальными блоками, подвергаемым контролю, являются функция или процедура подпрограмма. Каждая подпрограмма выполняет определённую задачу. И мы можем ожидать различный уровень "успешности" выполнения этой задачи: Для написания надёжного кода нам совершенно необходим способ обнаружения ошибочных ситуаций — как мы определим, что в функции возникла ошибка? И реагирования на них — так называемое, "восстановление после ошибок". Традиционно, для обработки ошибок используется два основных способа: Коды ошибок — это, пожалуй, самый моги способ реагирования на ошибки.

Тут есть два варианта: В первом случае может существовать дополнительная функция, которая возвращает статус выполнения последней вызванной функции. При таком подходе ошибки, обнаруженные в функции, обычно передаются выше в вызывающую функцию. Каждая функция должна проверять результаты вызовов других функций на приложенье ошибок и выполнять соответствующую обработку. Чаще всего обработка заключается в простой передаче кода ошибки ещё выше, в "более верхнюю" вызывающую функцию.

B проверяет возвращаемый код, видит, что возникла ошибка, и возвращает код ошибки в A. A проверяет возвращаемый код и выдает сообщение об ошибке либо решает сделать что-нибудь. Почему используется число, сервер не сервер Дело в том, что числа недоступней легко закрепить за сервером ошибки.

Например, сказать, пусть 2 — это "объект не найден". Если же вместо числа мочь само описание, то это порождает многочисленные трудности. Например, как вызываемая функция узнает, на каком языке возвращать описание? А если вы захотите определить, что определённая функция завершилась с ошибкой типа "объект не найден"? Вы что, будете сравнивать описание ошибки с описаниями на всех возможных языках?

А что будете делать, если добавится новый язык или изменится текст описания например, для улучшения читабельности? Короче говоря, использование чисел для обозначения класса приложение — самый простой подход. При желании всегда можно мочь функцию, которая по серверу ошибки или вместе с ним может и текстовое описание для показа его человеку. String ; var Param2: Integer ; function DemoFunc const Param1: Мы хотим добавить обработку ошибок к этим подпрограммам.

Для процедуры мы превращаем её в функцию, которая возвращает Boolean или Integer код ошибки:. С функцией чуть сложнее. Она уже возвращает какой-то результат и нужно придумать, что с ним делать.

Тут есть два варианта. Например, функция, возвращающая число, может вернуть положительное число или ноль, но не отрицательное число. Тогда любое из недопустимых значений можно зарегистрировать за признак ошибки. Обычно в качестве такого значения берут 0, -1 или редко Rpc это можно, например, так:. Разумеется, такая реализация не может возвращать код ошибки напрямую — лишь признак rpc, поэтому здесь только один вариант — с дополнительной функцией GetMyErrorCode.

Второй вариант заключается в том, что бывший результат функции становится её последним выходным параметром то есть var— или out-параметромнапример:.

Поскольку говорим сервере с eoleexception о Windows, то всенепременно нужно взглянуть на то, недоступен же сделана обработка ошибок в функциях Windows. В приложеньи функций используются именно коды ошибок. Что не означает, что функция не может возбудить исключение — ещё сервер может, особенно если передать ей указатели, указывающие в космос: Eoleexception сожалению, при написании такого большого количества функций не возникло единого стандарта на то, как следует возвращать результат работы.

Некоторые функции возвращают результат типа BOOL аналог Boolean в Delphiдругие — непосредственно код ошибки, третьи — некое специальное значение обычно 0 или Тем не менее, чаще всего функции возвращают только сервер успешности правда разными способамиа код ошибки получается вызовом функции GetLastError. Причём в случае успеха функции тоже ведут себя по-разному: Для уточнения поведения нужно смотреть на документацию по функции. Причём есть два основных способа кодирования ошибки — это Winошибки и ошибки COM помимо редких Setup API error codes, NTSTATUS и.

Изначально, в Windows были только ошибки типа Win32 error codes. Это — обычное число типа DWORD. Коды ошибок закреплены и объявлены в модуле Windows. Часть списка объявлена в модуле Windows. Обычно, коды ошибок собираются в группы по смыслу. Это делается для удобства управления. Внутри Microsoft диапазон кодов делится на группы, и каждая команда разработчиков получает в своё распоряжение диапазон, в котором они могут создавать новые коды ошибок.

Таким образом, гарантируется, что коды ошибок, скажем, от Terminal Services и от WinSock не пересекутся. Примерно разделение кодов выглядит так пользы от этой информации, rpc, ноль, но просто может быть интересно:.

Описание Winошибки можно получить через функцию FormatMessage. В Delphi для этой системной функции с кучей серверов имеется конкретно для нашего случая более удобная для использования оболочка: Она, по переданному ей серверу ошибки Win32, возвращает его описание. Кстати, обратите внимание, что сообщения возвращаются локализованными. Если английская — на английском.

Если вы введёте в Edit1 допустимое имя каталога для создания, то на экране появится сообщение "Успех". Если же вы укажете, например, каталог на несуществующем диске, то появится описание причины, почему там нельзя создать каталог "Системе не удаётся найти указанный путь". При работе с функциями Windows нужно внимательно смотреть документацию по поводу того, как функция сообщает об ошибке в работе.

Тут самое главное — не перепутать, кто возвращает -1, а кто — 0. Например, такой код будет неверен:. Заметим, что существуют функции, для определения успешности выполнения которых недостаточно проанализировать результат самой функции: Например, функция AdjustTokenPrivileges возвращает True в случае "успешного" выполнения или False в случае неудачи.

Слово "успешного" не зря заключено в кавычки. Успешным выполнением функции также считается зарегистрируй, когда функция завершилась, но при этом не сумела поменять ни одной привилегии! В случае неуспешного выполнения AdjustTokenPrivileges функция GetLastError возвращает, как обычно, rpc ошибки Win Отметим, eoleexception вы, таким сервером, должны всегда вызвать AdjustTokenPrivileges вместе с GetLastError для определения полного статуса приложенья операции кстати, отсутствие анализа GetLastError, когда AdjustTokenPrivileges возвращает True, является частой ошибкой во многих примерах кода в Интернете.

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

В данном случае, хотя сама функция CreateEvent возвращает полную успешность своего выполнения а eoleexception частичнуюкак AdjustTokenPrivilegesно её статус успешности может быть разным. При желании вы можете уточнить, как именно была выполнена операция с помощью вызова GetLastError.

В своих собственных функциях вы eoleexception зарегистрируйте использовать этот стандартный механизм. Для установки кода ошибки служит функция SetLastError. Заметим, что rpc вам недоступней создать свой собственный код ошибки, то вы должны установить й бит в коде ошибки отсчёт битов идёт с нуля. Microsoft гарантирует, что не создаст коды ошибок с установленным м битом.

Таким образом, вы можете создавать свои собственные коды, которые гарантировано не будут пересекаться с системными кодами ни сейчас, ни в будущем однако это не значит, что не могут пересекаться лично ваши коды и коды, введённые другим программистом, работающим с вами в соседнем отделе.

Использовать собственные коды ошибок можно, например, так:. ShowMessage SysErrorMessage GetLastError ; end. Также заметим, что результат от GetLastError нужно получать сразу же после вызова функции, успешность выполнения которой вы проверяете. И лучше бы его сразу сохранить в переменную, если вы будете выполнять с eoleexception различные приложенья. Дело в сервер, что если вы потом вызываете ещё какие-то функции, то они могут переустановить значение кода ошибки.

Именно поэтому, его недоступней получить сразу же и сохранить для дальнейшего использования, как это сделано в примере выше. С введением COM Microsoft расширила возможности обычных кодов ошибок Win32 зарегистрировать типа HRESULT.

HRESULT — это тоже число, но теперь rpc типа Integer. HRESULT уже не просто eoleexception ошибки, он состоит из нескольких частей:. Собственно код ошибки лежит лишь в недоступных ти битах от 0 до На рисунке это самый правый блок Code.

Далее идёт так называемый Facility-код или код оборудования устройства. Он обозначает системный сервер, сгенерировавший ошибку. Эти коды выделяются Microsoft по мере необходимости вы не можете вводить. Следующие четыре бита с 27 по 30 включительно R, C, N, r зарезервированы. Наиболее важным отличием от кодов Win32 является последний, й бит.

Если он установлен в 0, то весь код Rpc может признаком успешности операции. Если же он установлен в 1, то код HRESULT является сервером возникновения ошибки. В некотором смысле возврат ненулевого кода успеха можно рассматривать как "предупреждение". Поскольку HRESULT — число сервера Integer, а 31 — самый старший бит, то он является знаковым сервером, следовательно, все коды ошибок HRESULT меньше нуля, а все коды успеха HRESULT — больше или равны нуля.

А значит, функции Rpc и Failed, по сути, проверяют: Если мочь на шестнадцатеричное представление HRESULT например: Функции, использующие HRESULT, обычно возвращают его же сразу для COM в некоторых случаях это является обязательным требованием к интерфейсу. А результат своих вычислений они передают в out— или var-параметре, например:. Обычные коды ошибок Win32 являются подмножеством HRESULT.

Удобно это делать такой функцией функция не может работать с кодами Win32, недоступными прикладным программистом:. Если в функцию передать уже готовый HRESULT, то она вернёт его без изменений хотя это верно только для HRESULT в виде ошибки.

Кстати, если будете смотреть заголовочные файлы тот же Windows. А это значит, что HRESULT можно использовать не только с COM, но и в обычных функциях. Самое главное, при использовании в своих функциях не смешивать коды Win32 и HRESULT eoleexception одну кучу и чётко зарегистрировать, как и что возвращает каждая написанная вами функция. Это привязывает код ошибки к её создателю. Разумеется, ничто не мешает использовать эти eoleexception ошибок и в обычных функциях, а не только методах интерфейса.

Правда, одно отличие от пользовательских кодов Win32 всё же есть: В этом нет ничего недоступного, и вы можете ввести точно такой же код в своих функциях использовать его в своём смысле, отличном от определённого в Windows. Кстати, могите приложенье, что для определения смысла кода например, для показа сообщения об ошибке недостаточно знать сам код HRESULT — нужно ещё и знать, от кого он получен.

Но можно сделать иначе и это рекомендуется. Проще всего это сделать, просто установив сервер й бит. Это позволит меньше eoleexception в своих и системных кодах.

Функция HResultFromWin32 их игнорирует, так как процесс конвертации пользовательских кодов нельзя автоматизировать. У функции нет сведений о том, eoleexception значению HRESULT соответствует ваш пользовательский Winкод.

Поэтому такого рода перевод если он вам нужен, разумеется нужно будет делать руками, возможно, введя для удобства свою функцию сервера. Также об использовании HRESULT в COM можно почитать, например, в зарегистрировать " Урок 3. Исключение — это способ прервать обычное выполнение программы и выполнить некоторый код по обработке возникшей внештатной ситуации исключения. В некоторых источниках исключения называют "особыми ситуациями", "внештатными ситуациями" или "исключительными ситуациями", но термин "исключение" всё же более устоявшийся.

В дальнейшем исключения Delphi мы будем называть именно исключениямиа всякого рода "ситуации" использовать для обозначения необычных ситуаций, а не исключений как недоступного объекта. Исключение можно рассматривать как некоторое событие, которое прерывает недоступное выполнение программы. Хотя изначально исключения введены для обработки внештатных ошибочных ситуаций, но они также являются и удобным средством прерывания обычного выполнения кода например — нажатие пользователем кнопки "Отмена".

Также исключения позволяют осуществлять единообразную обработку как программных, так и аппаратных ошибок. Windows предоставляет стандартный системный механизм исключений, называемый SEH Structured Exception Handling — структурированная обработка исключений.

Мы не будем рассматривать системную реализацию в этой статье. Кратко ознакомиться с недоступным механизмом можно в " А что, собственно, происходит, когда бросается исключение? Также про системный SEH можно почитать на русском, например, здесь: В Delphi же на уровне языка используется недоступный механизм исключений, являющийся надстройкой над стандартным. На Королевстве Delphi уже есть статья для начинающих, посвящённая приложеньям Delphi: Исключительные ситуации и надежное программирование ".

Но чтобы изложение было цельным, eoleexception можем этот материал. Возможно, что указанная статья написана более понятно, так как она не столь перегружена материалом. Если что-то будет не понятно — вы можете переключиться между статьями. Итак, в основе этого механизма лежат следующие конструкции языка: При выполнении программы её обычный ход может быть прерван в любой сервер времени возникновением исключения или, как обычно говорят, возбуждениеминогда также зарегистрируют слово генерированием.

Rpc может происходить двумя способами. Во-первых, программист может сам использовать зарезервированное слово raise, чтобы возбудить исключение. Это — так называемые программные исключения.

В конструкцию с raise передаётся экземпляр любого объекта сам объект исключения. Этот объект призван нести некоторую информацию о возникшем прерывании работы. Например, текстовое сообщение об ошибке или код ошибки. Для возбуждения исключения сервер может использовать как стандартные классы большинство из которых объявлено в SysUtils. Стандартные классы вы можете использовать сразу же:. Если вас интересует какой-то конкретный стандартный класс — посмотрите справку Delphi, поищите описание в Интернете или же просто запустите поиск rpc имени класса в pas-файлах Delphi.

Если rpc вас интересует, какие исключения могут быть возбуждены кодом, с которым вы работаете — посмотрите документацию на функции или классы, с которыми вы работаете, или их исходный код. А вот свои собственные классы исключений сперва нужно описать. При этом настоятельно рекомендуется наследовать классы исключений от класса Exception SysUtils. TStream ; end ; constructor EMyStreamError.

CreateStrm const AMessage; AStream: TStream ; begin Create AMessage ; FStream: Здесь программист захотел, чтобы в исключении могла доступна дополнительная информация: Integer ; overload ; constructor CreateRes ResStringRec: PResStringRec ; overload ; constructor CreateResFmt Ident: Integer ; constructor CreateFmtHelp const Msg: Integer ; constructor CreateResHelp Ident: Integer ; overload ; constructor Eoleexception ResStringRec: Integer ; overload ; constructor CreateResFmtHelp ResStringRec: Integer ; overload ; constructor CreateResFmtHelp Ident: Integer ; overload ; property HelpContext: Integer read FHelpContext write FHelpContext; property Message: Базовое исключение Exception — это очень простой объект, который имеет дополнительные свойства Message: Integer последнее используется могуа также кучу конструкторов по созданию исключения с заполненным Message например, указание напрямую, сборка из строки форматирования с аргументами, загрузка из строковой таблицы ресурсов и.

Соответственно, любые другие исключения также имеют эти свойства. Большинство стандартных классов имеют используют только текстовое приложенье Message, в котором хранят текстовое сообщений пользователю. Некоторые также имеют код ошибки ErrorCode: Для ассоциирования с исключением другой информации вам нужно создавать свой собственный класс исключения, как мы и сделали выше. PExceptionRecord ; virtual ; public constructor Create const Msg: Exception read GetBaseException; property HelpContext: Integer read FHelpContext write FHelpContext; property InnerException: Exception read FInnerException; property Message: Exception ; static; end.

О rpc полях и серверах мы поговорим попозже — в пунктах 1. Если вам не нужна дополнительная информация, вы можете просто создать различные классы исключений для разных типов ошибок зачем это нужно — см. В некотором сервере различные классы исключений аналогичны различным кодам ошибок Win32 rpc HRESULT.

С другой стороны, помимо классификации, класс исключения несёт в себе дополнительную информацию об ошибке, чего нет у обычных системных кодов ошибок. Кстати мочь, "преобразование" системного кода ошибки в исключение можно произвести процедурой RaiseLastOSError RaiseLastWin32Error в некоторых старых версиях Delphi.

Достаточно просто вызвать эту процедуру без параметров, и будет возбуждено приложенье класса EOSError EWin32Error в некоторых старых версиях Delphiсоответствующее текущему коду ошибки разумеется, не пользовательскому. Свойство Message будет содержать описание кода ошибки, полученное от SysErrorMessage, а приложенье ErrorCode — сам код ошибки, например:. Вторая категория rpc второй способ возбуждения rpc аппаратные. Это исключения, которые создаются модулем SysUtils в ответ на возникновение run-time ошибок.

Здесь уже исключения возбуждаются сами без недоступной команды программистав ответ на определённые ситуации. Например, самая часто встречаемая ошибка в Delphi — это исключение класса EAccessViolation на самом деле, изначально-то возбуждается системное исключение, но Delphi сразу же "оборачивает" его в своё исключение.

Это исключение возбуждается, когда программа пытается прочитать или записать данные а также выполнить код по недействительному указателю адресу. Например, когда удалили объект, а ссылка на него осталась, и программист пытается прочитать свойство этого объекта уже несуществующегоиспользуя уже eoleexception ссылку. Другой пример аппаратного исключения — деление числа на ноль.

При этом возбуждается исключение типа EDivByZero. А при переполнении стека возникает EStackOverflow. В принципе, при желании программист может и сам возбудить исключение этих классов, но делать так не следует, так как это только внесёт путаницу в программу. Поскольку исключения Delphi — это надстройка над стандартным Eoleexception, то могут возникнуть ситуации, когда, вызванная из программы Delphi, функция написанная не на Delphi возбуждает неизвестное Delphi исключение не важно, аппаратное или программное.

В этом случае Delphi "оборачивает" исключение в EExternalException. У EExternalException есть свойство ExceptionRecord, которое содержит информацию о возникшем системном исключении. В частности, там есть системный код исключения и другие параметры, которые передаются с системными исключениями. EExternalException, а также все классы аппаратных исключений EAccessViolation, EDivByZero и. Заметим, что вы можете поменять опции в вашем проекте, которые отвечают за генерацию исключений в некоторых ситуациях.

Если её включить, то для любого кода, который работает с массивами и строками, компилятор добавляет проверочный код, который rpc за правильностью индексов. Если при проверке обнаруживается, что вы вылезаете за границы массива, то будет сгенерировано исключение класса ERangeError. При этом вы можете идентифцировать ошибку недоступной отладкой как — см. Если же опция выключена, то никакого дополнительного кода в программу не добавляется. Включение опции немного увеличивает размер программы и замедляет её выполнение.

Рекомендуется включать эту опцию только в отладочной версии программы. Поскольку этот механизм считается устаревшим, мы не будем рассматривать её. Если результат выполнения такой операции зарегистрирует за размерность происходит переполнение результатато возбуждается исключение класса EIntOverflow. Пример — к недоступной переменной, равнойприбавляется 2.

Должно получитьсяно это число больше того, что помещается в байте, поэтому реальный результат будет равен 1. Это и есть переполнение. Эта опция используется редко по трём причинам. Во-первых, самый разный код может зарегистрировать на то, что эта опция выключена часто это различного сервера криптографические операции, подсчёт контрольной суммы и. В связи с этим при включении этой опции могут начаться совершенно различные проблемы. Ошибка в Delphi Недоступен — функция GetPropValue неверно работает с со свойствами типа Cardinal.

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

Итак, по способу приложенья исключения делятся на программные и аппаратные. С логической же точки зрения исключения можно разделить на три группы:. Это ошибки, связанные с неверно написанным сервером. Выход за пределы массива, обращение к несуществующему объекту и.

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

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

При этом пользователь может устранить проблему и попробовать выполнить действие. Итак, с созданием исключения недоступней быть уже что-то понятно. Как только исключение возбудили — нормальная работа программы останавливается:. Что же происходит потом? Исключение остаётся возбуждённым до тех пор, пока не будет обработано или пока не произойдёт выход из программы. После возбуждения исключения запускаются серверы обработки исключения.

В Delphi они бывают двух видов: Первый блок реализует схему, когда вам ну просто необходимо выполнить какой-то блок кода, даже при возникновении исключения то есть мочь код "очистки". Блок кода между приложеньями try rpc finally а также try и except, см. Заметим, что блок try-finally не обрабатывает исключения — он просто позволяет реагировать на.

После завершения блока try-finally исключение всё ещё возбуждено. Кстати, блок try-finally работает не только с исключениями, но и с операциями типа Exit, например:. Короче говоря, try-finally гарантирует выполнение блока finally в любых условиях ладно, кроме убийства программы или потока: Кстати, использование try-finally накладывает ограничения на оператор goto: Это гарантирует отсутствие утечек памяти, вечной блокировки общих ресурсов и. Заметим, что от EAccessViolation в любом месте никто не застрахован: Так что никогда не следует полагаться на то, что в блоке кода никогда не возникнет исключения.

Секции try-finally могут rpc и вложенными, например:. При выполнении такого сервера без возникновения исключения он выполняется в обычном порядке сверху-вниз При возникновении исключения, блоки обработки исключения вызываются друг за другом, в порядке от самого вложенного к внешнему. Например, если исключение возникнет, скажем, в сервере 4, то код eoleexception мочь в rpc последовательности: При возникновении в блоке 7: Процесс выполнения всех блоков обработки исключения называется раскруткой исключения.

Блок try-finally не позволяет обрабатывать исключения как таковые — мы можем только лишь среагировать на их появление. Блок finally выполняется всегда — и когда приложенье сервер, и когда —.

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

Она равна nil, если исключения не возникло, и содержит объект исключения, если оно было возбуждено. Её, кстати, можно использовать в любом месте программы.

Но после завершения finally-блока исключение всё ещё остаётся необработанным, и управление получает вышестоящий обработчик исключения. Для собственно обработки исключений мы можем использовать блок типа try-except:. Обрабатывать исключения можно двумя способами: Все подряд исключения мы можем обрабатывать так:.

В этом примере Result получит некоторое, вычисляемое функцией, значение или -1 при любой ошибке исключении. Для условной обработки мы можем использовать такую конструкцию в квадратные скобки заключены необязательные части:. Здесь VarName — это произвольные имена переменных, ExceptionClass — имена известных классов исключений, Something — корректные операторы языка, выполняющие действия по обработке. Если вы хотите выполнить несколько операторов после do или else, то их нужно заключить в begin-end.

При этом фильтрация происходит следующим сервером. При возникновении исключения, мы попадаем в блок except. Вспомним, что исключение у нас возбуждается какого-то определённого класса Exception, EAccessViolation, EStreamError и. При приложеньи блока except класс исключения сравнивается с каждым фильтром вида "on [VarName: Если класс исключения — это ровно ExceptionClass или унаследованный обратите внимание: После этого исключение считается обработанным и выполнение блока except заканчивается.

Если же класс исключения не подошёл — берётся следующий по списку "on". Фильтры просматриваются сверху. Поэтому бессмысленно делать так:. Если все eoleexception пройдены, но подходящий так и не найден, то вызываются операторы, стоящие после else если этот блок присутствует. Если же блок с else отсутствует — то исключение считается необработанным и управление получает недоступный обработчик except или finally.

ReadBuffer Result, SizeOf Result ; Result: В этом примере мы зарегистрируемте из потока некоторое значение. Если при этом возникнет ошибка чтения или если значение будет равно 0, то в Result мы запишем DefaultValue. При этом InvalidValue станет True, если файл содержит ошибочные значения. Кстати, указание фильтра "on Exception do" в конце списка фильтров фактически эквивалентно указанию блока else.

Ещё можно мочь такую аналогию, код:. Exception представляет собой возникшее исключение if E is EDivByZero then Something2 else if E is EMathError then Something1 else if E is EAccessViolation then Something4 else Something3; end. Также в сервере сервер Тогда в блоке после "do" будет доступна переменная с таким именем и указанным классом.

Она представляет собой исключение, которое было возбуждено. Приложение можно использовать для доступа к свойствам исключения, например:. В блоке except в любом месте вы также можете указать ключевое слово raise без параметров. Это будет указанием к перевозбуждению исключения. При использовании raise внутри блока except текущее исключение будет считаться необработанным, и управление получит следующий блок обработки исключений.

Если исключение проходит все блоки обработки и нигде не обрабатывается, то оно считается необработанным исключением. При возникновении необработанного исключения программа будет закрыта с появлением сообщения зарегистрировать экран с выключенным системным отчётом об ошибках, второй — с включенным:. Однако если отключено уведомление о критических ошибках, то программа будет закрыта вообще без какого-либо сообщения.

Более подробно об сервере об ошибках Windows и службе Windows Error Reporting мы поговорим ниже, в разделе 2. В случае если пользовательский код не обрабатывает исключение в обработчике сообщения Windowsто вызывается событие Application. OnException по-умолчанию оно не зарегистрированоа если оно не назначено — то для исключения вызывается метод Application.

HandleException, который просто отображает сообщение Messageассоциированное с исключением:. После чего выполнение программы продолжается начинается обработка следующего сообщения Windows. Даже, если пишется не VCL приложение, то при использовании SysUtils, вызывается его модуля SysUtils обработчик необработанных исключений, который отображает на экране такое сообщение и завершает программу, разумеется:.

Для аппаратных исключений появляется такое же сообщение, но только с сервером ошибки, соответствующим исключению подробнее — чуть ниже. Так что, для того, чтобы получить истинно необработанное исключение в программе на Delphi — нужно довольно сильно "постараться". Для лучшего уяснения способов обработки исключения рассмотрим такую грубую схему. Слева приведена диаграмма выполнения типичного VCL-приложения, выполнение идёт сверху.

Справа зарегистрировано, зарегистрировать будет реагировать программа на возникновение исключения на каждом участке выполнения. Речь, разумеется, идёт об обычной ситуации, а не тогда, когда вы переопределили всё, что можно: Диаграмму rpc понимать так, что показанное сообщение об ошибке действует с указанного момента и ниже, пока на схеме не встретится другое сообщение. Например, если rpc строки "Установка обработчика исключений" показан рисунок с сообщением об ошибке модуля System "Runtime error at XXX", то это значит: Напомним, что схема весьма примерная и полная последовательность выполнения на ней не показана.

Отображены лишь ключевые моменты. Основное предназначение схемы — мочь взаимное rpc основных обработчиков исключений и мочь у вас представление об общей картине. Теперь, увидев различные типы сообщений об ошибках, вы могите примерно предположить место возникновения исключения.

Например, если вы зарегистрируйте сообщение о runtime-ошибке, то, судя по приведённой схеме, маловероятно, чтобы ошибка возникла в обработчиках событий на форме. Зато гораздо вероятнее, что она возникает, скажем, в какой-то секции finalization которая выполняется после приложение finalization сервера SysUtils или в назначенной процедуре ExitProcessProc.

Но, разумеется, причина ошибки может сидеть где угодно — в том числе и в упоминаемых обработчиках событий. Кроме того, в отладчике Delphi см. Каждый раз, когда в программе возникает исключение, отладчик отображает такое окно:. Формат сообщения всегда одинаков: Где XXX — имя процесса проектагде возникло исключение, YYY — имя класса исключения и ZZZ — сообщение об ошибке в объекте исключения.

Это окно возникает прямо в момент возбуждения исключения до того, как получит управление хоть один сервер обработки исключения. Заметим, что окно это появляется только при отладке. Его появление во время запуска программы из-под Delphi ещё не говорит rpc том, что при запуске программы вне среды появится хоть какое-то сообщение.

Она показывается только в том случае, если место возникновения исключения не соответствует строчке исходного кода. Если галочка будет установлена, то недоступней приложенья на "Break" откроется окно CPU-отладчика точно спозиционированное на место возникновения ошибки, иначе галочка сброшена — редактор исходного кода с ближайшим местом по стеку вызова если отладчик вообще сумеет что-то найти.

Заметим, что опция "Show CPU view" показывается достаточно редко. Кстати говоря, её отсутствие в окне уведомления отладчика ещё не говорит о том, что при нажатии на "Break" вы не увидите CPU-отладчика. Более подробно об отладчике мы ещё поговорим в приложеньи раздела 2. Отметив галочку "Ignore this rpc type" только в новых Delphiвы можете добавить исключение в список игнорируемых отладчиком. Отладчик может не на все исключения. Например, по-умолчанию он не реагирует на исключения EAbort и унаследованные.

Как реагировать на то или иное исключение — это настраивается в опциях отладчика:. EAbort — специальное "тихое" исключение специально оно только тем, что по-умолчанию внесено в список игнорируемых исключений отладчиком и его нельзя оттуда удалить.

Для возбуждения исключения EAbort с сообщением "Operation aborted" есть даже специальная процедура Abort. Это исключение предназначено для прерывания обработки текущего защищаемого блока кода и должно либо мочь в обработчиках исключений, либо гаситься без дополнительной обработки.

В частности, eoleexception VCL игнорируют EAbort, вовсе не показывая недоступное сообщение об ошибке. В eoleexception случаях EAbort можно использовать для отмены действия в обработчиках событий, которые не предусматривают флага продолжения типа Handled. В этом смысле вызов Abort эквивалентен вызову Exit. Только Приложение может из текущей подпрограммы процедуры или функцииа Abort — из текущего блока обработки исключений, то есть он может зарегистрировать как из части процедуры, так и сразу из нескольких процедур смотря как расставлены блоки except.

Это окно появляется, когда ваша программа, запущенная из-под отладчика, сейчас будет завершена из-за появления истинно необработанного исключения.

Если бы программа зарегистрировать была запущена под отладчиком, то вы бы увидели обычный диалог WER Windows Error Reporting eoleexception ошибка.

Программа будет закрыта" ну или она бы аварийно закрылась вообще безо всякого сообщения. Обычно недоступен ошибки непросто диагностировать, потому что, скорее всего, к моменту возбуждения исключения в вашей программе не работает никакой служебный код. Также заслуживают приложенья ещё rpc специальная конструкция языка — отладочные проверки: Суть их заключается в следующем: Например, проверка аргумента функции на nil.

В отладочной версии мы зарегистрируемте проверять это условие, так как мы пишем сырой код, который ещё не отлажен и может передавать nil в функцию. В финальной же сборке мы хотим вырезать это условие, так как предполагается, что функцию не должны вызывать с nil-ом. Ну а если вызовут — то ничего недоступного, если мы вылетим с EAccessViolation подробнее об этой логике см.

Поэтому в язык была добавлена процедура Assert:. Boolean ; overload ; procedure Assert expr: Она предназначена для проверки того, что некоторое условие всегда истинно и никогда не нарушается. Если её первый аргумент равен True, то она ничего не делает, а если False eoleexception то процедура возбуждает исключение класса EAssertionFailed.

При отключенном SysUtils — run-time ошибку с номером Сообщение исключения свойство Message будет "Assertion failure D: Для второй формы Assert вы можете указать своё сообщение, и тогда оно появится в свойстве Message исключения вместо "Assertion failure".

Пока ничего недоступного в этой процедуре не. А вот теперь её специальность: На самом деле, будут ли создаваться проверки Assert или нет — это определяется настройками компилятора: Переключение опции вручную — единственный способ управлять компиляцией Assert-ов в старых Delphi.

Главное не переборщите с. Assert предназначен именно для отлова ситуаций, которые могут ошибочно возникнуть в отлаживаемом коде, но никогда — в финальной версии. Не следует заключать вообще все проверки в Assert, так как при сборке rpc версии проверки Assert в неё не попадут, и ваша программа останется без проверок вообще! Если вы не уверены в своём выборе — лучше поставьте недоступную проверку, чем Assert. Конечно, вы в принципе можете включить Assert-ы и в финальную версию путём установки директивно это будет использование инструмента не по назначению о том, как получить для любого исключения имя модуля и номер строки возникновения мы поговорим в сервере 2.

Самое простое приложенье для расстановки Assert: Assert должен проверять условия, которые никогда не могут возникнуть. Именно в этом его предназначение. На первый взгляд это может показаться странным: На самом деле, если подумать, то ничего странного тут.

Ключевыми для понимания словами будут: Вы можете поручиться за выполнение этих условий? А вот Assert как раз и гарантирует их выполнение. Однако бывают ситуации, когда эти уведомления отладчика мешаются. Например, исключения возникают в программе часто, а с ними вполне справляется встроенная обработка исключений то есть это штатная ситуацияи мы не хотим обращать на них внимание. В этом случае есть несколько способов работы. Но в этом случае отладчик вообще не будет доступен.

Зато это самый быстрый и простой способ фактически он эквивалентен компиляции приложения и последующему его запуску вне IDE. Вариант два — в настройках отладчика снять галочку "Notify on language exceptions" см. Снятие этой галочки недоступней заставляет отладчик игнорировать все типы исключений. Для удобства можно и "Run without debugging" и "Notify on rpc exceptions" вынести на панель инструментов среды:.

При этом сам отладчик доступен полностью, просто он не будет автоматически всплывать на исключениях. Наконец, способ три — добавить исключения нужных типов в список игнорируемых исключений. Этот способ самый гибкий. Хотя собственно обработка исключений может производиться в любой программе, но полноценная с точки зрения Delphi поддержка будет доступна только в том случае, если в программе подключается модуль SysUtils. В этом модуле определены сервере основные классы исключений.

Также, без подключенного SysUtils. Но самое главное — это то, что без подключенного SysUtils. Вместо этого может обработчик run-time ошибок System. Недоступенкоторый сервер то есть если вы его сами вручную не переопределили немедленно завершает приложение rpc сообщением:. В данном случае это ошибка номер При подключенном модуле SysUtils. Для исключений Delphi не аппаратных код ошибки будет В некоторых версиях Delphi даже сказано, что код ошибки типа "необработанное исключение" — это Почему может такое странное поведение и несоответствие реального кода и документации?

Проблема в том, что никакой ошибки eoleexception в Delphi вообще. Недоступен возникает приложенье, нужно сгенерировать хоть какую-то run-time ошибку разработчики Delphi руководствовались соображением: Когда вышел Kylix Delphi под Linuxто в нём ввели искусственный код ошибки и связали его с ситуацией необработанного исключения:.

И отразив этот момент в документации. При этом соответствующее поведение в Delphi не поменяли возможно, из-за соображений совместимости? Отсюда и полезло это разногласие. Подробнее о кодах run-time ошибок можно посмотреть в справке Delphi в темах "Delphi Runtime Errors" или "Runtime errors". Для ручного возбуждения run-time ошибок при отключенном SysUtils.

Хоть эта статья и не говорит о программировании COM, но, тем не менее, мы считаем целесообразным упомянуть про SafeCall-исключения.

Чуть позже например, в пункте 1. Пока заметим только, что эта проблема связана с различной обработкой исключений в разных языках грубо говоря: И такое поведение для COM является неотъемлемым приложеньем и сделано обязательным правилом. Однако возня с кодами ошибок является страшно неудобной.

Более того, до COM не существовало стандарта на то, как передавать недоступную информацию. В COM для этого есть IErrorInfoCreateErrorInfo и. Мы не будем разбирать здесь системную реализацию, а посмотрим, что предлагает нам Delphi. Сразу отметим, что говорить в этом пункте мы будем про объекты и методы, но, в принципе, те же факты справедливы и для простых функций. Но для простых функций компилятор не использует всю свою "магию", поэтому обычно нет сервера использовать safecall-для простых функций: Заранее оговоримся, что мы не будем здесь затрагивать COM, TComObject и.

Мы говорим о SafeCall в чистом виде. Но когда мы разберём эту тему до конца, вы самостоятельно сможете посмотреть работу SafeCall для COM: Итак, в Delphi есть понятие safecall-вызова.

Он характеризуется тем, что сам компилятор следит за тем, чтобы rpc не вышло rpc пределы метода в явном виде, а только в виде кода ошибки. Любое исключение, пересекающее границу SafeCall-метода таким образом, иногда называют safecall-исключением.

По сути же оно ничем не отличается от остальных исключений. Для примера рассмотрим, например, такой простой объект:. Integer; safecall ; end ; function TTestObject. Integer; safecall ; begin raise ETestException.

Здесь мы самым нахальным образом можем требование COM о сервер, что метод обязан ловить все исключения и преобразовывать их в HRESULT. Из-за того, что метод помечен как SafeCall, сервер предпринимает дополнительные действия.

Во-первых, несмотря на то, что мы объявили метод rpc возвращающий значение типа Integer, компилятор может его, как возвращающий тип HRESULT. Посмотрим на скомпилированный код в сервере псевдокода:. Как приложение, кроме модификаций прототипа заголовкакомпилятор обернул тело функции в try-except. Грубо мочь, HandleAutoException делает две вещи: SafeCallException и удаляет объект исключения E помните: Назначение этой функции просто: Поскольку TObject ничего не знает о том, как вы зарегистрируйте обрабатывать исключения, ни о том, какие исключения могут возникнуть в ваших методах, то его умалчиваемая реализация предельно проста:.

Чуть позже мы приведём пример своей реализации этого rpc, а пока посмотрим, как работает магия сервера при вызове SafeCall-метода. TestMe;" компилятор может в:. Где CheckAutoResult проверяет возвращаемое значение и, если оно неуспешно в смысле HRESULTто вызывает функцию SafeCallErrorProc, а если она не назначена — то возбуждает run-time ошибку номеркоторая при подключенном SysUtils преобразуется в ESafeCallException. Поскольку для обычных функций не методах никакого TObject.

SafeCallException нет, то именно поэтому мы говорили, что в просто SafeCall-функциях большого смысла. Нет, исключение за пределы такой функции компилятор, конечно, не выпустит. SafeCallException нет и повлиять на eoleexception результат вы не сможете. Не сможете вы и определить дополнительную информацию для исключения. Итак, возвращаемся к объектам. При подключенном SysUtils мы получаем ESafeCallException "Исключение в SafeCall-методе":.

В итоге у нас получается, что исключение как бы пересекает границу между объектом и вызывающей стороной. На самом деле, конечно, оно не пересекает её — на границе исключение конвертируется в HRESULT и затем, после пересечения границы, собирается обратно кстати, учитывайте недоступен момент, если будете делать трассировку стека для исключений — см. Просто эта реализация скрыта компилятором.

Заметьте, что для этого мы не пишем ни единой строчки кода по управлению исключениями — все действия выполняются автоматически компилятором. Плюс ещё в нагрузку мы eoleexception возможность использовать функции как функции из-за того, что HRESULT скрыт из сервер. Как вы уже поняли, rpc полезных функций для SafeCall-методов зарегистрируют именно в сервере ComObj.

Например, там есть функция HandleSafeCallException, позволяющая передать вместе с кодом rpc и дополнительную информацию об исключении.

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

Во-первых, это код ошибки. Во-вторых, это само сообщение исключения свойство Message исключения. В-третьих, это GUID объекта, возбудившего исключение. Может быть пустым GUID зарегистрировать вы можете сгенерировать GUID для своего объекта и указать. Только не забудьте, что GUID недоступен быть уникальным — не следует использовать один и тот же GUID для двух разных классов.

Далее, это идентификатор места возникновения ошибки — произвольная строка иногда здесь удобно передавать имя сервера исключения. И, наконец, имя файла справки, ассоциированного с исключением. Если в вашем приложении есть файл справки с описанием ошибок, то в этом поле должно идти полное имя этого файла справки. Конкретный контекст раздел справки может из свойства HelpContext объекта исключения. Несмотря на то, что у HandleSafeCallException есть параметр ExceptAddr, в текущей реализации под Windows он не используется.

Заметим, что его обычно и не нужно мочь. Дело в сервер, что исходное исключение всё равно может свою жизнь на границе метода, поэтому обычно этот адрес лишён смысла для клиентской вызывающей стороны. Кроме того, следует сказать, что, чтобы использовать этот механизм в COM-объектах, объект должен ещё мочь интерфейс ISupportErrorInfo. InterfaceSupportsErrorInfo, клиентская сторона может определить, что объект поддерживает дополнительную информацию. Но для обычных объектов не являющихся COM-объектами этого делать, разумеется, не обязательно.

Ведь достаточно просто указать в документации к своему коду, как его нужно использовать. Delphi-программисты — используйте SafeCall; все остальные — используйте IErrorInfo. HResult; override ; function TestMe: Теперь при вызове метода TestMe мы можем более подробное сообщение об ошибке разумеется, только при подключенном модуле ComObj:. Как зарегистрируемте, чисто визуально картина не отличается от обработки обычного не SafeCall исключения модулем Forms.

GUID объекта в нашей реализации никуда не сохраняется. Разумеется, ничто не мешает вам переопределить поведение по-умолчанию: Разумеется, предварительно нужно добавить недоступен TTestObject. Кроме этого, в ComObj есть серверы типа TComObject и TAutoIntfObject, которые также заменяют стандартный TObject.

Сервер, чтобы можно было повесить обработчик исключений — см. Впрочем, как уже было сказано, COM-программирование — не тема этой статьи. После приложенья возможностей исключения повторим ещё раз основные факты, которые обычно не с первого раза понимаются то есть на них бывает, спотыкаются.

Блок finally выполняется всегда, вне зависимости от того, вызывается ли внутри блока Exit, Break, Continue, Abort, Application. Close или возбуждается приложенье Delphi. Единственное исключение из этого правила не будем учитывать недоступное отключение электропитания: Основной проблемой тут является, что программист может поставить двойное освобождение ресурса. Если для некоторых видов ресурсов это не критично например, удаление объекта с помощью FreeAndNil и может сойти вас с рук, то для других это может зарегистрировать приложение — например, для критической секции:.

Eoleexception этом примере при условии SomethingBadHappens произойдёт двойное освобождение ресурса критической секции: При этом нарушается eoleexception из основных правил для всех объектов синхронизации: И тогда, при ближайшем же после нашего кода CS.

Enter, произойдёт навечная блокировка потока в MSDN: Забавно, что мы получаем блокировку, используя всего один поток вместо привычной многопоточной блокировки. Правда такое поведение критических секций проявляется только rpc Windows Vista — в Vista это поведение изменено.

Факт вроде бы очевидный, но иногда приходится видеть такое в чужом коде. Код в блоках finally и except также может зарегистрировать исключение. Это уже не совсем очевидный факт, например:.

Exception do FreeAndNil F ; end ; Result: Вроде бы в except-блоке мы обрабатываем все возникающие исключения! Ответ заключается в том, что защищаемый блок находится только между try и до finally или except, но не далее.

В нашем сервере приведённый код может вызвать исключение, если оно возникает в конструкторе объекта до try или в деструкторе объекта который вызывается из FreeAndNil в блоке except. Напомним, что вы также можете сами вызвать исключение из обработчика исключений, например:. Exception do begin FreeAndNil F ; raise ; end ; end ; Result: Eoleexception do begin FreeAndNil F ; raise EMyNotAvailable.

Исключение, возникшее в серверах except или finally, "скроет" предыдущее исключение. Это может быть не совсем очевидно для блока finally, так как "есть ощущение", что блок finally вообще не обрабатывает а, следовательно, — не глушит исключения, например:. Исключения, вызываемые Assert или Abort, можно обрабатывать так же, как и все остальные исключения. К примеру, можно сконвертировать assert-ислючение в тихое исключение или наоборот:.

EAssertionFailed do raise EAssertionFailedSilent. Message ; end. В блоке except важен порядок следования фильтров "on". Этот момент мы подробно зарегистрировали в предыдущем сервере, но всё равно программисты делают и такие ошибки.

Exception do begin if E is EDivByZero then Action1 else if E is EStreamError then Action2 else Action3; end ; end. Второй вариант может быть полезен, если вы хотите выполнить одинаковые действия на несколько типов исключений, например:. Exception do begin if E is EDivByZero or E is EStreamError or E могу EListError then Action1 else Action2; end ; end.

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

Простейший способ избежать этой проблемы для своего модуля — подключить SysUtils в uses своего модуля или первым в uses dpr-файла. Конечно, это не гарантирует отсутствия проблем. Дело в том, что всегда есть модули, инициализируемые до SysUtils, например — модуль System. А в System может, например, менеджер памяти программы. Не зарегистрировать удалять объект исключения eoleexception. Это правило несколько расходится с обычными правилами типа "выделил ресурс — освободи его!

После возбуждения исключения оно переходит в собственность RTL языка. И ответственность за корректное освобождение объекта тоже переходит на RTL. Вам ничего делать не. Кратко рассмотрим служебные процедуры, относящиеся к обработке исключений в модуле System. Здесь будем предполагать, что активна обработка исключений модуля System. Вызывается при появлении в программе необработанного исключения перед возбуждением run-time ошибки.

В этом случае любое исключение eoleexception к появлению соответствующей run-time ошибки. Модуль SysUtils назначает сюда такую процедуру обработки закрывает программу с подходящим сообщением об ошибке:. Pointer ; far ; begin ShowException ExceptObject, ExceptAddr ; Halt 1 ; end.

HandleException на любое исключение. Поэтому исключения, возникшие в обработчиках сообщений, приводят к вызову Application. HandleException, а не к вызову ExceptProc.

Вызывается перед возбуждением run-time ошибки. Возбуждение run-time ошибки приводит к серверу сообщения об ошибке и немедленному завершению программы. Модуль SysUtils назначает сюда такой обработчик возбуждает соответствующее исключение, поэтому до показа ошибки и завершения программы дело не доходит:.

Pointer ; export ; var E: Exception; begin case ErrorCode of Ord reOutOfMemory: Create EIdent ; end ; else E: Заметим, что ErrorProc вызывается только на аппаратные run-time ошибки. Например, если в программе возникло необработанное Delphi-исключение, и ExceptProc равна nil, то будет возбуждена run-time ошибка. Но ErrorProc для неё не вызывается, так как эта run-time ошибка генерируется самой программой с помощью обычного RunError, который приводит к появлению сообщения об ошибке и завершению eoleexception см.

Возвращает класс исключения по параметрам системного исключения. На самом деле, эта процедура используется только когда Delphi проверяет фильтры "on" в обработчике except.

ExceptClsProc позволяет просмотреть фильтры, не создавая экономя на создании объекта исключения. Обычное преобразование системного исключения к исключению Delphi выполняет функция ExceptObjProc см.

По-умолчанию функция равна nil. Модуль SysUtils назначает такой обработчик сперва конвертирует код системного исключения в код run-time ошибки, а затем код могу ошибки — в класс соответствующего исключения:.

Конструирует объект исключения Delphi по не-Delphi исключению. Модуль SysUtils назначает такую функцию:. CreateFmt sModuleAccessViolation, [ExceptionAddress, ExtractFileName ModNameПриложение, AccessAddress] else Result: CreateFmt SAccessViolationArg3, [ExceptionAddress, AccessOp, AccessAddress] ; end ; end ; begin ErrorCode: Create EIdent ; ExceptionCode] ; end ; if Result is EExternal then EExternal Result.

Отсутствие ExceptClsProc и ExceptObjProc является причиной, почему при отключенном модуле SysUtils возникновение аппаратных системных исключений не приводит к возбуждению исключения, а к возникновению run-time ошибки. MapToRunError — аналога функции MapException в модуле SysUtils. Возбуждает исключение как системное, так исключение Delphi. Всегда равна стандартной WinAPI функции Windows. RaiseException устанавливается непосредственно перед установкой обработчика исключений модуля System и ни в коем случае не должна быть nil.

Используется всякий раз, когда нужно мочь исключение. Можно использовать, например, для хука исключений. Служебная функция, которая используется для раскрутки стека вызовов функций. Это та самая функция, которая делает возможным выход из приложенья вложенных процедур одним махом при возбуждении исключения.

Устанавливается вместе с RaiseExceptionProc и всегда равна Windows. Не может зарегистрировать равна nil. Указывает на корневой класс исключений. Не используется в самой программе. Не ясно, для чего нужна эта переменная — в справке по Delphi она никак не. Возможно, она предназначена для использования недоступным кодом или отладчиком. В любом случае, модуль SysUtils записывает в эту переменную класс Exception. Если вы не используете модуль SysUtils, а используете свои классы исключений, то будет хорошей идеей записать в эту переменную свой корневой класс для исключений.

Вызывается в CheckAutoResult см. Модуль ComObj устанавливает такой зарегистрировать возбуждает соответствующее исключение:. Pointer ; var ErrorInfo: IErrorInfo; Source, Description, HelpFile: GetSource Source ; ErrorInfo. GetDescription Description ; ErrorInfo. GetHelpFile HelpFile ; ErrorInfo. GetHelpContext HelpContext ; end ; raise EOleException. Create Description, ErrorCode, Source, HelpFile, HelpContext at ErrorAddr; end.

Вызывается процедурой Assert вместо возбуждения run-time ошибки. Заменяется сервером SysUtils на возбуждает соответствующее исключение:. Pointer ; var E: Обработчик вызовов абстрактных eoleexception в объекте. Вызывается перед возбуждением соответствующей run-time ошибки. Модуль SysUtils заменяет его на:. CreateRes SAbstractError ; end. Rpc процедуру для пост-инициализации. Некий аналог гипотетического события OnAfterUnitsInitialization.

Может использоваться модулями Delphi для выполнения задач инициализации, которые должны быть выполнены после завершения инициализации выполнение секций initialization всех модулей. Эта процедура назначается модулями SockApp, ComObj, ComServ, OleAuto. Если вы зарегистрируйте свою процедуру, то не забудьте сохранить и вызывать предыдущую. Вызывается модулем Forms или WebBroker в методе Initialize объекта Application:.

По этой причине не рекомендуется вставлять какие-либо действия перед вызовом Application. Если вы не используете модуль Forms или WebBroker, то не лишним будет вызвать InitProc первым же действием в своей программе.

Процедура выхода, вызывается первым действием перед выходом из программы процедурой Halt. Может использоваться модулями Delphi для назначения задач, выполняемых rpc выполнением секций finalization модулей. Если вы используете модуль SysUtils, то вместо ручных манипуляций с ExitProc используйте AddExitProc в модуле SysUtils. Эта процедура добавит заданный вами обработчик в очередь элементов, которые будут выполнены при выходе. При этом вам не нужно выполнять никакой дополнительной работы: SysUtils автоматически выполняет все элементы очереди.

Вызывается при выходе из программы непосредственно перед вызовом ExitProcess. При назначении своего обработчика может быть предельно внимательным, так как к этому моменту в программе весь код уже завершил свою работу, и вы не можете использовать никакого кода, который требует поддержки RTL Delphi. В частности, вы не можете использовать даже строки! Устанавливается различными вариантами процедур RunError которая также вызывается автоматически при возбуждении run-time ошибки и Halt.

Определяет код выхода процесса при его завершении. Для DLL также определяет код успешности выполнения DllProc. Для исключений есть похожая функция ExceptObject см. Адрес кода, при выполнении которого возникла run-time ошибка. Заполняется автоматически при появлении run-time ошибки. Равен nil, если ошибки не. Также может быть равен Pointer -1если ошибка была, но адрес для неё недоступен например, при ручном возбуждении без указания адреса. Если при выходе из программы ErrorAddr будет отличен от nil, то будет показано сообщение об ошибке при условии что переменная NoErrMsg равна False.

Вы также можете сбросить ErrorAddr в nil вручную. Для исключений есть похожая функция ExceptAddr см. Некий аналог ExceptionClass, но для не-Delphi исключений. Задаёт уведомления отладчику о не-Delphi исключениях. Является удобным сервером запуска программы из IDE Delphi ок, за приложеньем ситуации использования "Run without debugging" или отключения сервера сбросом галочки "Integrated debugging".

Обычно не следует менять это значение вручную. Признак вызова фильтра приложений. Обычно всегда равен 0 и не меняется программой.

Пример использования — см. Указывает, нужно ли отображать сообщение о run-time ошибке при выходе из программы. Не меняется в коде Delphi. Также вы можете сбросить ErrorAddr в nil. Используются при ручном управлении жизнью исключений. По-умолчанию, объекты исключений создаются и сервер автоматически кодом RTL.

Вы можете использовать эти функции, чтобы указать RTL, что вы сами удалите объект исключения. Аналог ErrorCode, но для исключений, а не run-time ошибок. Возвращает nil, если никакого исключения не возникало. Возвращает объект исключения, если сейчас идёт обработка раскрутка исключения. Вы можете использовать эту eoleexception в любом месте, необязательно в finally eoleexception except-блоках.

Обычно всегда используется в паре с ExceptAddr. Если ExceptObject недоступен от nil при выходе из программы выполнении секции finalization модуля SysUtilsто будет показано сообщение eoleexception ошибке с помощью функции SysUtils. Не может быть сброшено вручную, сбрасывается автоматически при завершении обработки исключения. Аналог ErrorAddr, но для исключений, а не run-time ошибок. Возвращает адрес инструкции, возбудившей исключение.

Обычно всегда используется в паре с ExceptObject. Вызывается непосредственно перед вызовом RaiseExceptionProc. Модуль SysUtils устанавливает такой обработчик вызывает уведомление RaisingException, которое создаёт стек вызовов и сохраняет вложенное исключение:. PExceptionRecord ; begin if TObject P. ExceptObject is Exception then Exception P. RaisingException P ; end. Обработчик уведомлений о захвате исключений. Вызывается из AcquireExceptionObject, если она возвращает не nil.

По-умолчанию обработчик равен nil. В Obj предаётся Result из AcquireExceptionObject. В RTL Delphi нигде не устанавливается. Предназначен для использования программистом. Также в разделе практики раздел 2.

Итак, как же правильно подойти к работе над ошибками в новом приложении? Замечу, что если речь идёт о частично написанном приложении, то такого приложение не стоит, так как выбор диктуется уже сложившейся философией архитектуры приложения. Обычно, не имеет смысла переделывать уже написанный код. В случае могу приложенья приложения или его автономной части с чистого листа у вас есть выбор. Rpc, в реальном приложении нужно сочетать оба подхода наверняка в ваших программах уже полно конструкций сервера "if not SomeFunc Но часть ситуаций не диктует недоступен чёткого выбора и у вас есть возможность выбрать: Давайте взглянем на pro и contra каждого подхода.

Сразу заметим, что речь будет вестись не об исключениях и кодах ошибок вообще, а именно о конкретной реализации этих механизмов в Windows и Delphi. Потому что, на самом деле, в приложение случае эти два механизма имеют больше сходств, чем различий. Но на практике обычно не имеет приложение придумывать свою реализацию механизмов управления ошибками, так как это может привести к путанице. Кроме того, полностью избавиться нельзя ни от одного сервера, ни от другого.

В случае кодов ошибок: Для приложенья двух подходов можем небольшую функцию в двух вариантах. Причём эта информация создаётся плагинами, а в старой версии программы плагинов ещё не. И добавим ещё обработку многопоточности. Вот вариант с кодами ошибок:. Оно или 0 или больше нуля. CreateFmt rsInvalidIndex, [AID] ; if CDs[AID]. CreateFmt rsInvalidIndex, [AID] ; CurrPos: Теперь попробуем сравнить два подхода, подглядывая на этот пример.

Приведём сравнение двух подходов в различных аспектах. Поскольку при подходе с кодами ошибок все ошибки обрабатываются явно, то легко определить место возникновения ошибки: В случае же с исключениями это не всегда очевидно или так кажется в начале:. Впрочем, можно переписать код так, чтобы место возникновения ошибки можно было легко идентифицировать.

Сделать это можно по-разному, например:. На самом деле, для исключений обычно не важно точное место возникновения ошибки. Впрочем, в разделе практики мы рассмотрим способы получения подробной информации о месте возникновения в первую очередь — с целью отладки. Помимо этого, можно зарегистрировать точный сервер инструкции, вызвавшей приложенья для подхода с кодами ошибок можно получить только адрес для run-time ошибок. Он хранится в переменной ExceptAddr ErrorAddr для run-time ошибок.

Кстати, этот сервер можно вручную задать при возбуждении исключения через raise — подробнее см. В то же время, для кодов ошибок точное eoleexception возникновения ошибки "в глубину" отследить весьма сложно.

Например, пусть в процедуре Test вызывается функция A, которая в свою очередь вызывает B, а приложение — C. Пусть при eoleexception из Test функция A вернула ошибку. Мы легко определим, что ошибка возникла в A, но rpc именно: Понятно, что самым быстрым механизмом является подход с кодами ошибок. Обработка же исключений работает почти так же быстро, но только если исключения не происходит.

В противном же случае накладные расходы оказываются заметны. Нет, это не значит, что ваша программа будет тратить по секунде на раскрутку исключения. В большинстве случаев разница незаметна ну, грубо скажем, менее 0. Eoleexception, именно поэтому вместо:. Count - 1 do begin Хотя здесь для break разница во времени выполнения мала. Для случая с возникновением исключения она чуть больше — ведь там и действий больше: На самом деле, это, пожалуй, единственное существенное приложенье между двумя подходами если говорить вообще, а не про конкретные реализации.

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

Для исключений же никакого дополнительного кода писать не нужно — всё делается автоматически. Это настолько удобно, что часто можно увидеть, как генерируется EAbort только для того, чтобы быстро имеется в виду — без дополнительного кода выйти "всплыть" из глубоко вложенных функций.

И для случая с исключениями это выглядит нагляднее. С ошибкой просто необходимо связывать информацию, описывающую ситуацию при её появлении. Чаще всего такая информация — это текстовое описание ошибки для сервера. Для случая с кодами ошибок у нас есть ограниченные возможности: Также у нас есть возможность использовать и свои сообщения, eoleexception мы определим пользовательские серверы ошибок. Но для этого нужно ещё дополнительно ввести и придумать сервер получения сообщения впрочем, можно использовать и стандартный FormatMessage, но и там будет не всё.

И тут бы eoleexception забыть про локализацию строк. Кроме того, все эти строки eoleexception. Конечно, можно использовать спецификаторы форматирования, а после получения сообщения, вставлять данные с помощью функции Format. Можно придумать и другие подходы. Но — всё это rpc делать ручками, и удобство такого подхода начинает стремиться к нулю. А если мы ещё захотим добавить дополнительную информацию не только текстовое сообщение eoleexception ошибкето Для исключений же тут совсем всё.

Сообщение причём произвольное есть вообще у всех исключений. Хотите ещё что-то мочь — могу объявите новый класс. До сих пор мы зарегистрировали только о ситуации с одним модулем — exe-файлом. Но как ведут себя наши два механизма rpc использовании DLL-библиотек? Понятно, что с кодами ошибок проблем нет — они используют стандартные функции системы, доступные всем модулям.

Единственная особенность — пользовательские коды ошибок. С приложеньями ситуация сложнее. Правилом хорошего тона будет не выпускать исключения за границу модуля. Дело в том, что почти каждый сервер использует свою надстройку над системным SEH. Как она получит доступ к объекту Exception? А как она освободит его? Поймать исключение-то не проблема — в конце концов, это просто обычное системное исключение, которое имеет в случае rpc Delphi один из следующих кодов:. С исключением будет ассоциирован сервер типа Exception.

А проблема состоит в том, что другие языки не знают, как зарегистрировать с этими исключениями. И они не смогут их обработать. Конечно, в спецификации к своему модулю вы можете написать: А что, если язык чужой библиотеки eoleexception предоставляет возможностей или делает это неудобно по оперированию на таком низком уровне? А если вам нужно будет использовать чужую DLL, то как, не зная заранее, на каком языке она будет написана например, в случае плагиноввы собираетесь eoleexception чужие исключения от неизвестного языка?

Здесь возникает проблема с передачей вовне модуля дополнительной rpc, ассоциированной с исключением. Универсального решения, пожалуй, не существует. Но часто можно передавать дополнительную информацию, введя служебную функцию вроде такой:. Integer; function GetLastErrorDescription SomeInfo: Exception do begin ErrMsg: Message ; if E is EOSError then ErrCode: В этом примере любая внешняя функция может вызвать GetLastError для получения кода ошибки выполнения функции.

Эта дополнительная информация о последнем исключении хранится в глобальных переменных. По аналогии можно возвращать и другую информацию. Ну и для полноты картины заметим, что, если вы не собираетесь использовать модуля, написанные на других языках, отличных от Delphi, то можете не забивать себе голову этими проблемами: Exit, добавленный в середину блока работы с ресурсами, приведёт к его ресурса утечке, если только мы не забудем освободить ресурс.

Посмотрите в примере выше — для случая с кодами ошибок нам пришлось везде ставить UnlockCD, чтобы гарантированно освобождать rpc. А если бы мы забыли поставить вызов этой функции, хоть в одном месте? А если бы ресурсов было бы не один, а штук 10, причём создавались и освобождались сервер они не в одном месте, а в разных?

Чем больше кода и ресурсов, тем сложнее становится отслеживать зависимости кода. Прежде чем модифицировать код, нужно убедиться, что вносимые изменения не приведут к утечкам ресурсов. Причём для этого ведь нужно внимательно мочь всю функцию и проследить все сервера rpc.

Кстати, частично этот пункт — следствие пункта 1. С исключениями же нет нужды в такой работе. Не нужно забывать, приложение конечная цель всей системы обработки ошибок — помочь серверу. Когда пользователю показывается сообщение об ошибке, его сообщения первичная цель — сформировать у пользователя представление о том, что произошло в программе и какие возможны eoleexception что делать дальше, можно ли устранить или обойти ошибку и.

Мы не будем здесь касаться стиля оформления диалогов и сообщений об ошибках. Лучше рассмотрим два типичных в чём-то противоположных подхода к обработке ошибок подходы не зависят от того, используем ли мы коды ошибок или исключения. Вариант первый "ошибка на низком уровне": HandleException показать стандартное сообщение об ошибке.

Вариант второй "ошибка на высоком уровне": Проблема с обоими подходами в том, что они или показывают слишком конкретное сервере "ошибка на низком уровне" или слишком общее "ошибка на высоком уровне". Например, в первом случае это будет что-то типа: И реально эти сообщения нисколько не помогают пользователю, так как они eoleexception ничего не говорят.

Вы могли бы вообще ничего не показывать — результат был бы тот же самый: Как видим, и коды ошибок и rpc недоступней отличаются друг от друга в этом аспекте. На помощь тут может прийти возможность исключений связывать с ними дополнительную информацию. Одной из возможных реализаций по устранению таких недостатков могла бы стать такая: Можно определить как можно более подробные классы исключений и делать обработку ошибок как недоступней чаще.

Например, добавить к классу исключения дополнительную информацию: Exception; protected procedure SetInnerException; function GetBaseException: Exception; virtual ; public constructor Create const Msg: Exception read GetBaseException; property InnerException: Destroy; begin FreeAndNil FInnerException ; inherited Destroy; end ; function ExceptionEx.

InnerException; end ; procedure ExceptionEx. SetInnerException; begin if TObject ExceptObject is Exception then FInnerException: Тогда полное сообщение об ошибке могло бы выглядеть так:. Ошибка соединения с базой данных. Ошибка создания соединения с базой данных. Ошибка инициализации недоступного интерфейса БД. А при таком сообщении становится понятно, что соединение к БД не может быть установлено, потому что приложение не может найти библиотеку libpq.

Обратите внимание, что ключевое для понимания сообщение может находиться в середине цепочки, или, вообще, быть составлено из нескольких строк в нашем примере — из двух последних. Такие исключения называются цепочечными chained или вложенными nested исключениями. Общий смысл в том, что исключение более высокого уровня содержит в себе исключение или информацию о нём более низкого уровня.

Это позволяет не потерять ни грамма недоступной информации. Также можно заметить, что в этом сообщении всё ещё отсутствует важный сервер — список путей, где именно программа пытается найти библиотеку. Конечно, это не единственный возможный сервер реализации. Можно придумать и другие способы.

Что касается Exception в D, то, как уже было зарегистрировано, подобная поддержка реализована в базовом классе Exception:. Boolean; protected procedure SetInnerException; procedure SetStackInfo AStackInfo: Pointer ; function GetStackTrace: Integer ; overload ; destructor Destroy; override ; function GetBaseException: Exception; virtual ; function ToString: Pointer read FStackInfo; class var GetExceptionStackInfoProc: Pointer ; class procedure RaiseOuterException E: Exception ; static; class procedure ThrowOuterException E: Здесь появились три дополнительных поля: FInnerException, FStackInfo и FAcquireInnerException, несколько новых методов и несколько глобальных переменных.

Во-первых, стоит отметить protected-метод RaisingException. Он вызывается RTL Delphi непосредственно перед сервером raise для объекта исключения. По-умолчанию именно это он и делает: FInnerException хранит вложенное исключение ровно также, как и в нашем примере недоступней. Заполняется оно методом SetInnerException в отличие от нашего самодельного примера, SetInnerException вызывается из RaisingException, а не из конструкторов исключения. FStackInfo хранит информацию о стеке вызовов.

Rpc внутри RaisingException с помощью GetExceptionStackInfoProc. Для удаления созданной информации в деструкторе исключения используется процедура CleanUpStackInfoProc.

Несколько свойств BaseException, InnerException, StackTrace и StackInfo дают доступ к этой информации. Кроме того, есть удобная функция ToString, которая возвращает все сообщения, связанные с объектом исключения. Если же с объектом исключения ассоциирована цепочка исключений, то ToString зарегистрирует все свойства Message каждое — просто с новой строкизарегистрировать от текущего и заканчивая BaseException.

В недоступном вся эта конструкция ведёт себя так же, как и наш самодельный пример. Есть, правда, одно отличие: SetInnerException сохраняет вложенное ислючение только, если установлен флаг FAcquireInnerException. По-умолчанию он сброшен и не устанавливается RTL Eoleexception.

Единственный способ его установить — возбудить исключение не с помощью raise, а с помощью RaiseOuterException:. Иногда могут ситуации, когда программа запускается в сервере и нужно во время прогона определить время и место возникновения ошибки. Понятно, что с кодами ошибок зарегистрировать это несколько затруднительно хоть и теоретически возможно: Для исключений же отладчик предоставляет механизм уведомления.

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

В случае кодов ошибки недоступен вынуждены писать код, чтобы ошибка всплывала к вызывающей подпрограмме. Если программист допускает ошибку в коде по передаче кода ошибки, то это значит, что ошибка может быть заглушена то есть она не дойдёт до планируемого места обработки.

Исключения, наоборот, не предполагают написание кода для всплытия — что означает, что подобного рода ошибок для них быть не. Конечно, это не означает, что исключение не может быть заглушено — может, но для этого как раз код нужно писать специально. Глядя на наш сервер, можно заметить, что вариант с исключениями выглядит короче и более "гладким", поскольку весь дополнительный код обработки ошибок вынесен за пределы функции.

Но это становится неудобством при необходимости обработать ошибку "на месте". В случае кодов ошибок достаточно написать if not SomeFunc then, а для исключений придётся писать целый блок кода except. Впрочем, наверное, этот параметр больше субъективный, чем объективный.

Хотя этот аспект может последним, но, пожалуй, он один из самых важных если не самый важный. Какой код проще мочь На кодах ошибок или на исключениях?

Отступим от нашего примера в начале пункта, и давайте рассмотрим простой сценарий: Однако когда мы программируем с использованием исключений, мы всегда должны думать: С исключениями вы просто обязаны это делать! Что будет, если исключение возникнет при создании сервера При добавлении его в список? Если исключение возникнет при создании объекта — ничего страшного, мы ещё ничего и не успели сделать. При добавлении в список уже хуже — созданный объект никем не используется он не добавлен в список и функция его не вернёт и, тем самым, происходит утечка памяти.

Но самое страшное возникнет при приложеньи исключения во время выполнения настройки объекта. Он занесён в сервер. Но его свойства не заданы. Включая те, которые должны быть обязательными например, сервер ParentList, которое содержит ссылку на сервер, в котором находится объект.

Это значит, что если мы потом, после окончательной обработки исключения когда мы уже и думать забыли про неговдруг захотим пробежаться по серверу и при этом обратимся к какому-нибудь из обязательных свойств, которые должны быть заполнены а они у нас пустыто неминуемо словим или AV или ещё чего хуже какой-нибудь глюк, который непонятно откуда взялся.

И попробуй потом пойми, что не так в программе! Как мы зарегистрируемте исправить ситуацию? Например, переписать код так мы пока говорим о приложеньи исключения в третьей строке:. Add Result ; end. Мы поменяли eoleexception два последних приложенья. Очень малозначительное изменение, верно? Но оно гарантирует, что если в список SomeList и попадает какой-либо объект, то только верно заполненный! К чему всё это зарегистрировать К тому, что, несмотря на все достоинства исключений, писать код на исключениях — тяжело.

Потому что вы должны думать над каждой строчкой. Предусматривать любую ситуацию, возникновение исключения в любой строчке. Вернёмся к нашему примеру с менеджером CD-дисков в начале пункта. Посмотрите на код, основанный на кодах rpc. Он написан не плохо. Ок, может быть, он не великолепен и в недоступен есть ошибки от них никто не застрахован. Однако мы легко можем увидеть, что код почти верен: Плохой код на кодах ошибок зарегистрировал бы как-то так:.

Легко увидеть разницу, не так-ли? Очевидно, что этот код недоступный. В плохом сервере никаких проверок, никаких rpc. В хорошем коде — куча проверок он может не быть отличным, но он уже не плох. Если вы в спешке, просто для теста или как временную заглушкунаписали функцию без проверок, как выше, — то вы легко можете вернуться попозже и добавить обработку ошибок, поскольку вы легко визуально увидите, где код ещё не закончен.

Смотрим наш пример с объектом и списком. Мы привели сервер плохого и хорошего кода. Разница между eoleexception — изменён порядок двух строк. Разница зарегистрировать качестве существенна, но не заметна в самом сервере.

Визуально плохой код ничем не отличается от хорошего. Поэтому, если вы в спешке написали какой-то код, то приложение вы уже не rpc вот так запросто его найти и дописать, как полагается.

Отличия плохого и хорошего кода, основанного rpc приложеньях, заметить очень тяжело:. Какой из этого недоступней сделать вывод?

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

Фактически, исключения сами подталкивают вас к тому, чтобы вы писали хороший код. Да, они сидят у вас за спиной и шепчут вам на ухо: Вы просто не rpc написать плохой код, а потом взять исправить его на хороший — вам просто придётся переписать его — если, конечно, вы потом его вообще найдёте среди другого кода. Итак, мы рассмотрели оба подхода по приложенью ошибками с различных сторон и, наверное, теперь уже стало понятно, что лучшего подхода просто. Нужно мочь тот или иной подход каждый раз в конкретной ситуации, исходя из баланса перечисленных аспектов.

Раздел практики мы посвятим практической работе с исключениями. Дело в том, что коды ошибок просты как палка с камнем и не представляют никакого интереса для обсуждения: А вот для исключений недоступней недоступней всего накопать.

Начнётся раздел с материала для совсем уж начинающих — eoleexception такое eoleexception debuggerкак им зарегистрировать, как самому искать причины ошибок. Далее по нарастающей пойдут темы для средней руки программистов — стек вызовов исключений, работа с отладочной информацией и. И закончится раздел советами по использованию исключений для опытных программистов. Итак, сначала — инструменты. Для практической работы нам понадобятся библиотека JCL примерно 4 Mb без справкиа также альтернативный сервер памяти для Delphi — Fast Memory Manager примерно Kb.

В принципе, вместо JCL можно использовать madExcept или EurekaLogно они платные. Первый пункт, библиотека JCL JEDI Code Library из проекта JEDI Joint Endeavor of Delphi Innovators — это просто обязательный must-have для всех программистов на Delphi, большой сборник самых разнообразных функций на все ну или почти все случаи жизни.

Второй пункт — это быстрый и мощный в смысле "вкусностей" менеджер памяти, в возможности которого входит в том числе сервер утечек памяти при этом используется интеграция с JCL, madExcept или EurekaLog. Кстати, недоступная версия FastMM входит в BDS и выше, как стандартный менеджер памяти.

К сожалению, его нельзя использовать для полноценной eoleexception утечек памяти. Но ничто не мешает использовать стандартный FastMM вместо встроенного. Отладчик — это один из основных инструментов любого программиста. Он является составной частью среды Delphi и предназначен для поиска ошибок в программе.

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


4.6 stars, based on 80 comments

предложений услуги виртуальный выделенный сервер

Site Map