Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.02.05;
Скачать: CL | DM;

Вниз

Обработка исключительных ситуаций без SysUtils   Найти похожие ветки 

 
Bopros   (2006-01-14 22:48) [0]

Необходимо обработать исключительную ситуацию без использования модуля SysUtils, вот элементарный пример, который выдаёт Runtime error 200:

program Project1;

uses
 Windows;

var b:integer;
begin
 try
   b:=trunc(b/0);
 except
   MessageBox(0,"123","321",mb_ok);
   end;
end.


 
Bopros   (2006-01-14 23:08) [1]

нашёл, читаю
http://www.delphikingdom.com/asp/viewitem.asp?catalogid=833


 
Bopros   (2006-01-14 23:46) [2]

а никто готовым примером не поможет?


 
Джо ©   (2006-01-15 00:42) [3]

> [2] Bopros   (14.01.06 23:46)
> а никто готовым примером не поможет?

Так в статье ж вроде и примеры имеются.


 
NightAngel   (2006-01-15 00:48) [4]

Можно обработать исключения через SEH без использования каких-либо модулей. В конечном итоге все конструкции типа try..except, try..catch, сводятся примерно к следующему (с небольшими вариациями):

PUSH OFFSET HANDLER
PUSH FS:[0]
MOV FS:[0],ESP
... // Здесь код, в результате выполнения которого может возникнуть исключение
POP FS:[0]
ADD ESP,4h
RET
HANDLER:
... // Здесь код обработчика исключения
MOV EAX,1  // если eax==1 управление передаётся следующему обработчику в цепочке
RET


 
Bopros   (2006-01-15 12:31) [5]

вообщем подкрепил err.pas из KOL и заработало все ок, и exe вырос не намного


 
Bopros   (2006-01-15 12:32) [6]

2 NightAngel

а можешь всё таки дать кусок кода для делфи для обработки вида
try
except
end;
?


 
Bopros   (2006-01-16 15:17) [7]

никто не поможет с кодом чтобы по минимум было?


 
Digitman ©   (2006-01-16 15:23) [8]


> кусок кода для делфи для обработки вида
> try
> except
> end;


Ты еще не осознал, какую глупость ты сморозил при этом ?


 
Игорь Шевченко ©   (2006-01-16 16:09) [9]


> Можно обработать исключения через SEH без использования
> каких-либо модулей. В конечном итоге все конструкции типа
> try..except, try..catch, сводятся примерно к следующему
> (с небольшими вариациями):


А finally ?


 
Владислав ©   (2006-01-16 16:43) [10]

А finally вроде и без SysUtils работает...


 
Игорь Шевченко ©   (2006-01-16 17:26) [11]

Владислав ©   (16.01.06 16:43) [10]

except тоже работает без SysUtils.

"Normal exception support comes from the SysUtils unit, which must be initialized before such support is available. " (c) F1


 
Bopros   (2006-01-17 15:02) [12]


> Digitman ©   (16.01.06 15:23) [8]
>
>
> > кусок кода для делфи для обработки вида
> > try
> > except
> > end;
>
>
> Ты еще не осознал, какую глупость ты сморозил при этом ?
>

и какую же интересно?

> Игорь Шевченко ©   (16.01.06 17:26) [11]
>
> Владислав ©   (16.01.06 16:43) [10]
>
> except тоже работает без SysUtils.

и где же работает? попробуй выполнить код, который в первом моём сообщении.


 
Игорь Шевченко ©   (2006-01-17 15:25) [13]

Bopros   (17.01.06 15:02) [12]

Да, не работает, это я малось погорячился. InitExceptions надо прикручивать, можно модифицированный.


 
Bopros   (2006-01-18 00:44) [14]

и всё таки если вернуться к http://www.delphikingdom.com/asp/viewitem.asp?catalogid=833 у кого нибудь работает пример оттуда?
вот код, может подскажете что я делаю не так?
http://rafb.net/paste/results/PKDbFs88.html
http://rafb.net/paste/results/sD4v1d94.html


 
Defunct ©   (2006-01-18 01:51) [15]

> Bopros

Позвольте поинтересоваться, откуда такая неприязнь к SysUtils?


 
Bopros   (2006-01-18 09:40) [16]


> Defunct ©   (18.01.06 01:51) [15]
>
> > Bopros
>
> Позвольте поинтересоваться, откуда такая неприязнь к SysUtils?
>

пишу приложение на WinAPI


 
Игорь Шевченко ©   (2006-01-18 11:52) [17]


> пишу приложение на WinAPI


пиши без try except

WinAPI исключений не возбуждает, проблем быть не должно.


 
Bopros   (2006-01-18 12:20) [18]

ну мне надо Except
помогите пожалуйста разобраться с  http://www.delphikingdom.com/asp/viewitem.asp?catalogid=833


 
Владислав ©   (2006-01-18 12:31) [19]


> Игорь Шевченко ©   (18.01.06 11:52) [17]
> ...WinAPI исключений не возбуждает...


Хммм... А EnterCriticalSection к WinAPI отношение имеет?


 
Игорь Шевченко ©   (2006-01-18 13:31) [20]

Владислав ©   (18.01.06 12:31) [19]

Имеет. А эта функция возбуждает исключение ?

Bopros   (18.01.06 12:20) [18]


> ну мне надо Except


InitExceptions надо прикручивать


 
Владислав ©   (2006-01-18 13:47) [21]


> Игорь Шевченко ©   (18.01.06 13:31) [20]
>
> Имеет. А эта функция возбуждает исключение ?


Platform SDK:
Windows 2000/NT:  In low memory situations, EnterCriticalSection can raise an exception.


 
Владислав ©   (2006-01-18 13:49) [22]

Могу ошибаться, но по моему, она (функция) не одна такая...


 
Игорь Шевченко ©   (2006-01-18 13:55) [23]

Владислав ©   (18.01.06 13:47) [21]

This function can raise EXCEPTION_POSSIBLE_DEADLOCK if the critical section is corrupt or deadlock detection is enabled. Do not handle this exception; either continue execution or debug the application.

Windows 2000/NT:  In low memory situations, EnterCriticalSection can raise an exception. To avoid problems, use structured exception handling, or call the InitializeCriticalSectionAndSpinCount function to preallocate the event used by EnterCriticalSection instead of calling the InitializeCriticalSection function, which forces EnterCriticalSection to allocate the event.


 
Владислав ©   (2006-01-18 14:16) [24]

Игорь, ну и? Что Вы хотели этим сказать? Я не понял.

P.S. Откуда вот это: "This function can raise EXCEPTION_POSSIBLE_DEADLOCK..."? Я не нашел.


 
Игорь Шевченко ©   (2006-01-18 14:53) [25]

Владислав ©   (18.01.06 14:16) [24]


> Что Вы хотели этим сказать? Я не понял.


Я поясню. Функции WinAPI не ориентируются на обработку исключительных ситуаций. И при их вызове тоже не надо ориентироваться на обработку. В случае Low Memory, например, стандартная обработка исключений Delphi скорее всего вызовет исключение из-за невозможности создать объект Exception, поэтому применительно к данной ситуация обработка бесполезна.


> Откуда вот это: "This function can raise EXCEPTION_POSSIBLE_DEADLOCK.
> .."?


http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/entercriticalsection.asp


 
Владислав ©   (2006-01-18 15:46) [26]

Ну хорошо. Откинем ситуацию low memory.

Цитата от туда же:
"Reading and Writing From a File View. (Здесь речь о memory mapped files).
...
Reading from or writing to a file view can cause an exception."

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

P.S. Спасибо за ссылку. Не знал я о декабрьском апдейте. Крайний раз ставил Platform SDK осенью с диска, что присылает Microsoft. Там еще был февраль 2003.


 
Джо ©   (2006-01-18 16:00) [27]

>  Игорь Шевченко ©

Исключения МОГУТ быть возбуждены в результате вызова многих функций из WinAPI. Даже банальное WriteProfileString("",nil,nil) вызывает EAccessViolation в дебрях ntdll (на XP, по крайней мере).


 
Игорь Шевченко ©   (2006-01-18 16:11) [28]

Джо ©   (18.01.06 16:00) [27]


> Исключения МОГУТ быть возбуждены в результате вызова многих
> функций из WinAPI


Я извиняюсь, это их документированное поведение ?

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


 
Digitman ©   (2006-01-18 16:18) [29]


> какую же интересно?


Да ту самую.

Эти страшные слова "try", "except", "finally" без Делфи и без реализованного в ней Objectpascal-компилятора попросту бессмысленны.


 
Игорь Шевченко ©   (2006-01-18 16:28) [30]

Владислав ©   (18.01.06 15:46) [26]

В большинстве случаев функции API возбуждают исключения в тех случаях (кроме Access Violation из-за неверно переданных параметров, разумеется), когда стандартная обработки исключений Delphi"ской библиотекой времени выполнения не приведет к желаемому результату. Поэтому для того, чтобы не усложнять себе жизнь, а заодно и не усложнять код, разумно придерживаться правила, что функции API исключений не возбуждают.


 
Джо ©   (2006-01-18 16:37) [31]

> [28] Игорь Шевченко ©   (18.01.06 16:11)
> Я извиняюсь, это их документированное поведение ?

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


 
Владислав ©   (2006-01-18 16:50) [32]


> Джо ©   (18.01.06 16:37) [31]


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


 
Джо ©   (2006-01-18 16:53) [33]

> [32] Владислав ©   (18.01.06 16:50)
> Речь о разумно написанной программе,
> которая не будет передавать подобные параметры.

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


 
Bopros   (2006-01-18 16:56) [34]


> Игорь Шевченко ©   (18.01.06 13:31) [20]
>
> Владислав ©   (18.01.06 12:31) [19]
>
> InitExceptions надо прикручивать

а подробнее можно?
интересует что неправильно сдела относительно статьи
http://www.delphikingdom.com/asp/viewitem.asp?catalogid=833
http://rafb.net/paste/results/PKDbFs88.html
http://rafb.net/paste/results/sD4v1d94.html


 
Владислав ©   (2006-01-18 17:03) [35]


> Джо ©   (18.01.06 16:53) [33]


Заметьте, я этого не говорил. И тем более я не пытаюсь выкидывать обработку исключений из программ на Delphi.

А если говорить о конкретном, а не на отвлеченные темы...
Что нужно было бы написать в обработчике исключения, возникшего в приведенном Вами в 27 посте примере? И что нельзя было бы написать до вызова этого примера, чтобы такое исключение не возникло?


 
Leonid Troyanovsky ©   (2006-01-18 17:08) [36]


> Джо ©   (18.01.06 16:37) [31]

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


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

--
Regards, LVT.


 
Игорь Шевченко ©   (2006-01-18 17:09) [37]

Джо ©   (18.01.06 16:37) [31]
Джо ©   (18.01.06 16:53) [33]

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


 
Джо ©   (2006-01-18 17:11) [38]

> [36] Leonid Troyanovsky ©   (18.01.06 17:08)
> Дык, он и так нарушается.
> После AV в дебрях ntdll честной программе остается лишь
> завершиться.



procedure TForm1.Button1Click(Sender: TObject);
begin
 try
   WriteProfileString("",nil,nil)
 except
   ShowMessage ("Function call failed.");
 end;
 ShowMessage ("Here we are!");
end;


Зачем честной программе завершаться после такого пустяка? ;)


 
Игорь Шевченко ©   (2006-01-18 17:15) [39]

Джо ©   (18.01.06 17:11) [38]

procedure TForm1.Button1Click(Sender: TObject);
begin
 GetWindowThreadProcessId (Handle, Pointer(123456768));
end;

Запусти


> Зачем честной программе завершаться после такого пустяка?
>  ;)


Чтобы программист исправил ошибку.


 
Владислав ©   (2006-01-18 17:16) [40]


> Джо ©   (18.01.06 17:11) [38]
>
>    ShowMessage ("Function call failed.");


Зачем пользователю программа, которая делает неверные вызовы функций, а потом об этом сообщает? :о)


 
Джо ©   (2006-01-18 17:18) [41]

> [37] Игорь Шевченко ©   (18.01.06 17:09)
> Джо ©   (18.01.06 16:37) [31]
> Джо ©   (18.01.06 16:53) [33]
>
> В этом случае обработка исключений мало чем поможет, если
> передан неправильный параметр.

Эту функцию я привел для примера. Но:
1. Никто не помешает вызываемой функции возбуждать исключение даже при правильном параметре (в том числе, и в результате ошибки человека, писавшего эту функцию).
2. А зачем  тогда вообще обработка исключений? Знай, пиши всегда правильно и ошибочных ситуаций возникать не будет.

Повторюсь, что ту функцию я привел как самый простой пример, что функции из Windows API МОГУТ возбуждать исключения. В т.ч., и недокумментированные.


 
Игорь Шевченко ©   (2006-01-18 17:21) [42]

Джо ©   (18.01.06 17:18) [41]


> 2. А зачем  тогда вообще обработка исключений? Знай, пиши
> всегда правильно и ошибочных ситуаций возникать не будет.
>


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


> 1. Никто не помешает вызываемой функции возбуждать исключение
> даже при правильном параметре (в том числе, и в результате
> ошибки человека, писавшего эту функцию).


В таком случае ошибка укажет программисту, что надо исправить. Пользователю ошибка программиста бесполезна.


 
VirEx ©   (2006-01-18 17:26) [43]

да что вы спорите, покопайтесь в InitExceptions и вытащите код


 
Джо ©   (2006-01-18 17:29) [44]

> [42] Игорь Шевченко ©   (18.01.06 17:21)

Мы говорим практически об одном и том же, просто я, наверное, не очень внятно изъясняюсь (горячий денек сегодня).

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


 
Leonid Troyanovsky ©   (2006-01-18 17:31) [45]


> Джо ©   (18.01.06 17:11) [38]

> Зачем честной программе завершаться после такого пустяка?


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

Т.е., без обработки автору можно было б рассчитывать на пару пинков,
а с оной - на повреждения средней тяжести ;)

--
Regards, LVT.


 
Игорь Шевченко ©   (2006-01-18 17:40) [46]

Джо ©   (18.01.06 17:29) [44]

Руссинович с Соломоном в своей книге "Внутреннее устройство Windows 2000" обсуждают причину появления синего экрана смерти. Ход рассуждений примерно такой - системе неизвестно, какие последствия повлечет ошибка, поэтому, во избежание, система просто останавливается, дабы не усугублять ситуацию. При этом проверок в системе, как ты понимаешь, предостаточно.

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


 
Джо ©   (2006-01-18 17:52) [47]

В общем, убедили меня в том, в чем я уже и был убежден :)
Всего лишь был ответ на [17], возможно, немного более эмоциональный, чем того стоила проблема.

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


 
Defunct ©   (2006-01-19 03:10) [48]

> Bopros
> пишу приложение на WinAPI

А почему бы не подключить SysUtils и не писать себе дальше на WinAPI?
Ведь объем добавляемый к exe файлу будет не так велик в пределах ~30kb.

если уж так невмоготу его использование, тогда последуйте совету Игоря Шевченко.. Сделайте InitExceptions, которую можете вырезать из SysUtils.


 
NightAngel   (2006-01-19 03:45) [49]

>  Bopros   (18.01.06 09:40) [16]

Если Вы хотите использовать только WinApi можете установить конечный обработчик исключений применяя функцию SetUnhandledExceptionFilter().
Как правило, обработчик устанавливается в основном потоке как можно ближе после точки входа программы. Поэтому он охватывает целую программу от точки входа до завершения. Нет никакой потребности удалять обработчик после завершения - это будет сделано автоматически Windows. Если же Вы хотите обрабатывать исключительные ситуации в каком-либо потоке, то Вам придется использовать SEH (каждый поток в вашей программе имеет различное значение сегментного регистра FS:[0], поэтому обработчик особых ситуаций будет определенным потоком). И ничего вырезать и прикручивать не нужно.


 
Игорь Шевченко ©   (2006-01-19 11:08) [50]

Встречный вопрос - никто не встречал статьи по организации обработки SEH в Delphi ? Интересна именно обработка SEH, а не Delphi"йских исключений - это все-таки разница, с доступом к EXCEPTION_POINTERS, CONTEXT, возможностью задавать EXCEPTION_CONTINUE_SEARCH, EXCEPTION_CONTINUE_EXECUTION.


 
NightAngel   (2006-01-21 02:09) [51]

> Игорь Шевченко ©   (19.01.06 11:08) [50]

Статей не встречал, но вот как это можно сделать в простейшем случае:


program TestSEH;
uses
 Windows;

type
 ValueReg=record
   SafeEip:DWORD; // Метка, куда нужно будет попасть после исключения
   PrevEsp:DWORD; // Предыдущее значение ESP
   PrevEbp:DWORD; // Предыдущее значение EBP
 end;

const
 ExceptionContinueExecution = 0;
 ExceptionContinueSearch    = 1;
 ExceptionNestedException   = 2;
 ExceptionCollidedUnwind    = 3;

 Caption     : PChar = "SEH Тест" + #0;
 NotOccured  : PChar = "Всё в порядке!" + #0;
 Occured     : PChar = "Исключение!" + #0;

var
 SEHReg      : ValueReg;
 Text        : PAnsiChar;

label
 SafePlace;

{$O+}
function Exception_Handler(
   ExceptionRecord:PExceptionRecord;
   EstablisherFrame:Pointer;
   ContextRecord:PContext;
   DispatcherContext:Pointer):DWord;cdecl;
begin
 ContextRecord.Eip := SEHReg.SafeEip;
 ContextRecord.Esp := SEHReg.PrevEsp;
 ContextRecord.Ebp := SEHReg.PrevEbp;
// Рестарт после инструкции вызвавшей исключение
 Result := ExceptionContinueExecution;
end;

{$O-}
begin
Text := Occured;
asm
  push offset Exception_Handler // Смещение на наш обработчик
  push dword ptr fs:[0]         // Адрес следующей структуры ERR
  mov  fs:[0], esp

  mov   SEHReg.SafeEip, offset SafePlace
  mov   SEHReg.PrevEsp, esp
  mov   SEHReg.PrevEbp, ebp
end;
asm
  xor   eax, eax          // Вызываем исключение (код защищенный обработчиком)
  mov   [eax], 1
end;
Text := NotOccured;
SafePlace:
asm
  pop   dword ptr fs:[0]  // Восстановить структуру ERR в FS:[0]
  add   esp, 4            // Очищаем стек
end;
MessageBox(0,Text,Caption,MB_OK or MB_ICONINFORMATION);
end.


EIP,ESP,EBP можно не сохранять в глобальной переменной, а помещать их значения в стек. И еще, обязательными полями являются только запись EXCEPTION_REGISTRATION (указатель на предыдущую запись и указатель на наш обработчик), но никто не запрещает перед указателем на обработчик поместить в стек и другие параметры, в частности, safeplace и EBP. Стандартов здесь нет. В Delphi, кстати, метка, куда нужно будет попасть после исключения, специально не сохраняется, а используется комбинация из 2-3-х jmp-ов. Примерно вот так:


_try                         // Устанавливаем SEH
 push _jmp_to_SEH   // В стек помещается  не сам обработчик, а jmp на него
 push fs:[0]
 mov fs:[0],esp
...
_except:                   // :=safeplace
...
_end:
 pop fs:[0]
 add esp,4
 jmp _continue              // Обходим прыжки для продолжения
_jmp_to_SEH:
 jmp @_except_handler  // Переход на универсальный обработчик
 jmp _except                // Сюда обработчик возвращает управление
_continue:
...
function @_except_handler(...):integer; // Универсальный обработчик
asm
...
 mov edx,[esp+8]  // Адрес EstablisherFrame := Exception_Registration
 mov edx,[edx+4]  // Адрес обработчика := _jmp_to_SEH
 add edx,5           // Прибавляем длину инструкции jmp и получаем адрес инструкции jmp _except для возврата
...
end;


Удачи!



Страницы: 1 2 вся ветка

Текущий архив: 2006.02.05;
Скачать: CL | DM;

Наверх




Память: 0.63 MB
Время: 0.028 c
15-1137190602
LordOfRock
2006-01-14 01:16
2006.02.05
Способы оплаты онлайн


15-1137528952
Nous Mellon_
2006-01-17 23:15
2006.02.05
Демократия в деле.


2-1137836536
Clock
2006-01-21 12:42
2006.02.05
Часы


15-1137150188
Думкин
2006-01-13 14:03
2006.02.05
Информатик-аналитик


15-1137410283
G707
2006-01-16 14:18
2006.02.05
Задачка, вроде простая, но...