• Познакомьтесь с пентестом веб-приложений на практике в нашем новом бесплатном курсе

    «Анализ защищенности веб-приложений»

    🔥 Записаться бесплатно!

  • CTF с учебными материалами Codeby Games

    Обучение кибербезопасности в игровой форме. Более 200 заданий по Active Directory, OSINT, PWN, Веб, Стеганографии, Реверс-инжинирингу, Форензике и Криптографии. Школа CTF с бесплатными курсами по всем категориям.

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

  • Автор темы Akupaka
  • Дата начала
A

Akupaka

Всем привет.

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

Кому интересно, из практики:
- результат функции не инициализируется, если в ней возникла необработанная исключительная ситуация, даже, если перед ее возникновением этот результат был назначен.
Т.е.:
Код:
Function F1() As Variant
F1 = False
Error 1000, "Some error"
End Function

Sub Initialize()
' так использовать нельзя
On Error Resume Next
If F1() Then
Msgbox "F1 returned True"
End If

' так лучше
Dim F1Res as Variant
On Error Resume Next
F1Res = F1()
If F1Res Then
Msgbox "F1 returned True"
End If

' причем, если F1Res используется для возврата значений нескольких функций, то перед вызовом функции ее (F1Res) необходимо сбрасывать!
Dim F2Res as Variant
On Error Resume Next
F2Res = True
F2Res = F1() ' F1() не вернула результат, но и не сбросила состояние F2Res!!! F2Res == True из предыдущего состояния
If F2Res Then
' ЭТОТ код выполнится ошибочно
Msgbox "F1 returned True"
End If
End Sub

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

ToxaRat

Чёрный маг
Green Team
06.11.2007
3 332
42
BIT
0
юзай GetThreadInfo
Код:
Code	Meaning
LSI_THREAD_LINE	Current Line Number 
LSI_THREAD_PROC	Name of current procedure
LSI_THREAD_MODULE	Name of current module
LSI_THREAD_VERSION	LotusScript version number
LSI_THREAD_LANGUAGE	(Human) language setting
LSI_THREAD_COUNTRY	Country or region setting
LSI_THREAD_TICKS	Get current clock ticks
LSI_THREAD_TICKS_PER_SEC	Get clock ticks per second (supported only on platforms that support parallel processing primitives)
LSI_THREAD_PROCESS_ID	Get current process ID (supported only on platforms that support parallel processing primitives)
LSI_THREAD_TASK_ID	Get current task ID (supported only on platforms that support parallel processing primitives)
LSI_THREAD_CALLPROC	Get the name of the calling procedure
LSI_THREAD_CALLMODULE	Get the name of the calling module
для обработки ошибок самое оно
 
N

nvyush

Если лень объявлять обработчики в вызываемых процедурах, то можно, конечно, и такое сваять:
Код:
Sub Test()
On Error Goto Err1
Call Sub1()
On Error Goto Err2
Call Sub2()
On Error Goto Errh
ExitProc:
Exit Sub
Err1:
Msgbox "Error call Sub1"
Resume ExitProc
Err2:
Msgbox "Error call Sub2"
Resume ExitProc
Errh:
Msgbox "Error in Test"
Resume ExitProc
End Sub
Я предпочитаю объявлять обработчики ошибок явно во всех вызываемых процедурах/функциях в стиле
P.S. Ни разу не удалось трассировкой вызовов уронить Лотус.
 
A

Akupaka

P.S. Ни разу не удалось трассировкой вызовов уронить Лотус
Може я особенный? :) На каком-то из N-уровней вложенности у меня стабильно валился клиент. Был какой-то из 6/7 нотесов.
Спасибо за статью!
 
N

nvyush

Може я особенный? :) На каком-то из N-уровней вложенности у меня стабильно валился клиент. Был какой-то из 6/7 нотесов.
Где-то натыкался на информацию, что недокументированная функция Lsi_info не является thread-safe, т.е. если её дёргают несколько потоков, то можно уронить клиента/сервера. Особенно актуально для сервера. Поэтому лучше использовать GetThreadInfo.

P.S. Тут обсуждалось:
 
O

Omh

Я поступаю так же как nvy, обработчик ошибок в каждой процедуре/ф-ии локальный (т.е. не возвращает ошибку наверх).
 
T

turumbay

- результат функции не инициализируется, если в ней возникла необработанная исключительная ситуация, даже, если перед ее возникновением этот результат был назначен.
и рыпку съесть и .... :)
хочеца одновременно и значение вернуть и исключение бросить? так не бывает :)
про getthreadinfo: можно смело использовать константы, объявленные в хелпе.
по теме есть классика от A. Guirard:
Еще один вариант хэндлера попадался недавно в шаблоне discussion 8.5. (lslib)lsClassException.
 
A

Akupaka

Я поступаю так же как nvy, обработчик ошибок в каждой процедуре/ф-ии локальный (т.е. не возвращает ошибку наверх).
А он разве так делает? :) Если он делает так же как в статье, то там обработка ошибок поднимается наверх, но с трейсом.

nvy
Если я правильно помню, то я записывал значения из GetThreadInfo (но не помню точно или из LSI_info) в свой массив! Т.е. не так как в статье.
Так как в статье я тоже делаю обычно, только по-своему группирую. Но в случае с функциями так делать нельзя, почему писал выше.

Добавлено:
хочеца одновременно и значение вернуть и исключение бросить? так не бывает :)
Бывает, но надо немного допилить :) т.е. исключение "поднять" в вызывающей функции. Т.е. как в лотусе часто бывает - через жп.
 
N

nvyush

Я поступаю так же как nvy, обработчик ошибок в каждой процедуре/ф-ии локальный (т.е. не возвращает ошибку наверх).
Не, я поступаю не так. В библиотеках обработчик ошибки возвращает ошибку наверх, а вот в кнопках и событиях ошибки обрабатываются и логируются. В результате всегда (почти) можно посмотреть, откуда у ошибки "ноги растут".

Добавлено:
Но в случае с функциями так делать нельзя, почему писал выше.

При возникновении ошибки в функции возможны два подхода. Либо функция генерит ошибку и не возвращает ничего вразумительного, либо внутри себя сбрасывает ошибку и возвращает Null, Nothing, Empty, False и т.д. Это к вопросу об использовании конструкцци On Error Resume Next — её использование оправдано в исключительных случаях (и побольшей части из-за лени программиста нормально обработать ошибки).
 
O

Omh

Ну, значит, так как nvy, но ошибку наверх не возвращаю.
Другими словами, не так :) :)

Чёт я слажал немного :)
Смотрю в книгу, вижу фигу.
 

Medevic

Что это ? :)
Green Team
10.12.2004
3 334
1
BIT
4
При возникновении ошибки в функции возможны два подхода. Либо функция генерит ошибку и не возвращает ничего вразумительного, либо внутри себя сбрасывает ошибку и возвращает Null, Nothing, Empty, False и т.д. Это к вопросу об использовании конструкцци On Error Resume Next — её использование оправдано в исключительных случаях (и побольшей части из-за лени программиста нормально обработать ошибки).
Да можно и ошибку вернуть и значение. Только зачем?
 
T

turumbay

Бывает, но надо немного допилить ;) т.е. исключение "поднять" в вызывающей функции. Т.е. как в лотусе часто бывает - через жп.
Это не через жп. Это подход, принятый в цивилизованных языках, поддерживающих исключения. Если функция бросила исключение - она не возвращает результата. Грубо говоря - она возвращает объект исключения.
Да можно и ошибку вернуть и значение.
Ниче не понимаю... Если функция бросает исключение - она ничего не возвращает. Или не так? Можно конечно по сишной традиции возвращать код ошибки, а значение возвращать через входной параметр функции. Но речь вроде идет именно об исключениях?
 

Мыш

Lotus Team
12.02.2008
1 213
29
BIT
43
А если ошибка возникает уже в обработчике ошибки? Скажем, обработчик уже произошедшей ошибки хочет отправить сообщение по почте, создать документ в базе, зачистить какие-то файлы на уровне ОС и т.п. - и вновь вызывает ошибку. Я в таких случаях пишу "... resume next"...
 
T

turumbay

Да? Значит я думаю через жп ))
Меня бы лично такое поведение(значение + exception) повергло в шок:
Пользователь: Компьютер, скока будет дважды два?
Компьютер: Четыре, и, кстати, у тебя канал до сервера отвалился!
Как документировать такую функцию: всегда возвращает верное значение, но иногда при этом бросает ошибку?
Очевидно напрашивается разделение функции на две, каждая из которых будет занимаца своим делом.
 

Medevic

Что это ? :)
Green Team
10.12.2004
3 334
1
BIT
4
Ниче не понимаю... Если функция бросает исключение - она ничего не возвращает. Или не так? Можно конечно по сишной традиции возвращать код ошибки, а значение возвращать через входной параметр функции. Но речь вроде идет именно об исключениях?
Исключение мы обработаем внутри. Но с помощью Err можно узнать номер ошибки после выхода из функции. И при желании вызвать еще одно исключение.
Короче, пример. В результате получим и 5, и обработаем ошибку.
Код:
Sub test
On Error Goto e
Msgbox(Cstr(errtest))
If Err Then Error Err
Exit Sub
e:
Msgbox Error
Resume
End Sub

Function errtest As Long
On Error Goto e
Dim a As Long, b As Long
b = 1
errtest = 5
errtest = b / 0
Exit Function
e:
Exit Function
End Function
 

Мыш

Lotus Team
12.02.2008
1 213
29
BIT
43
В результате получим и 5, и обработаем ошибку.

А какая польза-то от этой пятерки? Она же не есть правильное значение, полученное в результате выполнения функции. Хотя если использовать возвращаемое значение как нумератор строк кода... ;)
 

Medevic

Что это ? :)
Green Team
10.12.2004
3 334
1
BIT
4
А какая польза-то от этой пятерки? Она же не есть правильное значение, полученное в результате выполнения функции. Хотя если использовать возвращаемое значение как нумератор строк кода... ;)
Да хз. Я таким не пользуюсь. :)
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!