Текущий архив: 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