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

Вниз

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

 
Владислав ©   (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.58 MB
Время: 0.028 c
2-1137622320
serko
2006-01-19 01:12
2006.02.05
Qreport!


15-1137267901
Ермак
2006-01-14 22:45
2006.02.05
Сайт по BlackBox


1-1135970052
Allegarh
2005-12-30 22:14
2006.02.05
Поддержка нескольких языков в программе


3-1133935957
fedpavel
2005-12-07 09:12
2006.02.05
_RecordSet


4-1133008773
vvvaaa
2005-11-26 15:39
2006.02.05
Как активизировать окно