Обработка ошибок в Lua
Обработка ошибок во время выполнения программы необходима. Непредвиденные ошибки могут возникать при файловых операциях, передаче данных и вызовах веб-служб. Если информацию об ошибке не обрабатывать должным образом, это может привести к утечке информации, сбою программы и другим проблемам.
Любой язык программирования требует обработки ошибок. Типы ошибок включают:
- Синтаксические ошибки
- Ошибки времени выполнения
Синтаксические ошибки
Синтаксические ошибки обычно вызваны неправильным использованием компонентов программы (таких как операторы и выражения). Простой пример выглядит следующим образом:
-- test.lua 文件 a == 2
Результат выполнения приведённого выше кода:
lua: test.lua:2: syntax error near '=='
Как видите, выше произошла синтаксическая ошибка; один знак "=" отличается от двух знаков "=". Один "=" — это выражение присваивания, а два "=" — операция сравнения.
Другой пример:
Пример
print(a)
end
При выполнении вышеуказанной программы возникнет следующая ошибка:
lua: test2.lua:2: 'do' expected near 'print'
Синтаксические ошибки проще, чем ошибки времени выполнения программы. Ошибки времени выполнения не могут указать конкретную ошибку, но синтаксические ошибки можно быстро устранить. Например, в приведенном выше примере нам просто нужно добавить "do" под оператором for:
Пример
do
print(a)
end
Ошибки времени выполнения
Ошибка времени выполнения возникает, когда программа выполняется нормально, но выводит сообщение об ошибке. В следующем примере возникает ошибка во время выполнения из-за неправильного ввода параметра:
function add(a,b) return a+b end add(10)
Когда мы компилируем и запускаем следующий код, компиляция может завершиться успешно, но во время выполнения возникнет следующая ошибка:
lua: test2.lua:2: attempt to perform arithmetic on local 'b' (a nil value) stack traceback: test2.lua:2: in function 'add' test2.lua:5: in main chunk [C]: ?
В Lua при вызове функции, даже если список фактических параметров и список формальных параметров не совпадают, вызов всё равно может успешно выполниться. Лишние параметры будут отброшены, а отсутствующие параметры будут заполнены nil.
Приведённое выше сообщение об ошибке возникло потому, что параметр b заполнен nil, а nil участвует в операции +.
Еслиaddвнутри функции — не"return a+b"а вместо этого"print(a,b)"тогда результат станет"10 nil"ошибка не будет выведена.
Обработка ошибок
Мы можем использовать две функции: assert и error для обработки ошибок. Пример ниже:
Пример
assert(type(a) == "number", "a is not a number")
assert(type(b) == "number", "b is not a number")
return a+b
end
добавьте(10)
При выполнении вышеуказанной программы возникнет следующая ошибка:
lua: test.lua:3: b 不是一个数字 stack traceback: [C]: in function 'assert' test.lua:3: in local 'add' test.lua:6: in main chunk [C]: in ?
В примере assert сначала проверяет первый параметр. Если проблемы нет, assert ничего не делает; в противном случае assert выбрасывает второй параметр как сообщение об ошибке.
Функция error
Формат синтаксиса:
error (message [, level])
Функция: завершает текущую выполняющуюся функцию и возвращает содержимое message в качестве сообщения об ошибке (функция error никогда не возвращает управление)
Обычно error добавляет некоторую информацию о местоположении ошибки в начало сообщения.
Параметр Level указывает, откуда получить местоположение ошибки:
- Level=1 [по умолчанию]: позиция вызова error (файл + номер строки)
- Level=2: указывает, какая функция вызвала функцию, которая вызывает error
- Level=0: не добавлять информацию о местоположении ошибки
pcall и xpcall, debug
Для обработки ошибок в Lua можно использовать функцию pcall (защищённый вызов), чтобы обернуть код, который нужно выполнить.
pcall принимает функцию и параметры, которые нужно ей передать, и выполняет её. Результаты выполнения: с ошибкой, без ошибки; возвращаемое значение: true или false, errorinfo.
Формат синтаксиса следующий:
if pcall(function_name, ….) then -- 没有错误 else -- 一些错误 end
Простой пример:
Пример
33
истина
> =pcall(function(i) print(i) error('error..') end, 33)
33
false stdin:1: error..
> function f() return false,2 end > if f() then print '1' else print '0' end 0
pcall вызывает первый параметр в "защищённом режиме", поэтому pcall может перехватить любую ошибку во время выполнения функции.
Обычно, когда возникает ошибка, вы хотите получить больше отладочной информации, а не только местоположение ошибки. Но когда pcall возвращает управление, часть содержимого стека вызовов уже уничтожена.
Lua предоставляет функцию xpcall. xpcall принимает второй параметр — функцию обработки ошибок. Когда возникает ошибка, Lua вызывает функцию обработки ошибок до того, как стек вызовов развернётся, поэтому вы можете использовать библиотеку debug в этой функции, чтобы получить дополнительную информацию об ошибке.
Библиотека debug предоставляет две общие функции обработки ошибок:- debug.debug: предоставляет пользователям приглашение Lua для проверки причины ошибки
- debug.traceback: строит расширенное сообщение об ошибке на основе стека вызовов
>=xpcall(function(i) print(i) error('error..') end, function() print(debug.traceback()) end, 33)
33
stack traceback:
stdin:1: in function <stdin:1>
[C]: in function 'error'
stdin:1: in function <stdin:1>
[C]: in function 'xpcall'
stdin:1: in main chunk
[C]: in ?
false nil
Пример использования xpcall 2:
Пример
n = n/nil
end
function myerrorhandler( err )
print( "ERROR:", err )
end
status = xpcall( myfunction, myerrorhandler )
print( status)
При выполнении вышеуказанной программы возникнет следующая ошибка:
ERROR: test2.lua:2: attempt to perform arithmetic on global 'n' (a nil value) falseДругие расширения