Обработка ошибок: pcall и error
Учимся ловить ошибки так, чтобы программа не падала целиком.
pcall (protected call) — функция, которая вызывает другую функцию «под защитой»: если внутри случится ошибка, программа не упадёт, а сообщит о проблеме.
Ошибки неизбежны: пользователь ввёл текст вместо числа, файл не нашёлся. Без защиты любая ошибка останавливает всю программу. В игре это означает вылет — недопустимо.
Генерация ошибки: error
Функция error намеренно вызывает ошибку с сообщением:
local function divide(a, b)
if b == 0 then
error("деление на ноль!")
end
return a / b
endЕсли вызвать divide(10, 0) напрямую — программа аварийно остановится с этим сообщением.
Защита через pcall
pcall запускает функцию безопасно и возвращает два значения: успех (true/false) и результат либо текст ошибки:
local function divide(a, b)
if b == 0 then error("деление на ноль!") end
return a / b
end
local ok, result = pcall(divide, 10, 2)
print(ok, result)
local ok2, err = pcall(divide, 10, 0)
print(ok2, err)Вывод:
true 5 false деление на ноль!
При успехе ok равен true и второе значение — результат. При ошибке ok равен false и второе значение — сообщение об ошибке. Программа продолжает работать!
Типичный шаблон
local ok, result = pcall(riskyFunction)
if ok then
print("Успех:", result)
else
print("Поймана ошибка:", result)
endСхема защищённого вызова
pcall(f)
├─ f отработала ──> true, результат
└─ f бросила error() ──> false, текст ошибки
(программа НЕ падает)Как работает под капотом
Внутри pcall Lua устанавливает «точку восстановления» перед вызовом функции. Если случается error, исполнение «отматывается» назад к этой точке вместо аварийной остановки. Есть и расширенная версия xpcall, которая дополнительно принимает обработчик для красивого сообщения со стеком вызовов.
Частые ошибки
- Вызывать функцию как
pcall(divide(10, 0))— это сначала выполнитdivide(и упадёт). Правильно:pcall(divide, 10, 0)— передаём функцию и аргументы по отдельности. - Игнорировать первое значение
okи сразу использовать второе как результат. - Заворачивать в
pcallвообще всё подряд, скрывая баги вместо их исправления.
Итог
error("текст")намеренно генерирует ошибку с сообщением.pcall(f, аргументы)вызывает функцию под защитой и возвращаетokи результат/ошибку.- При
ok == falseвторое значение — текст ошибки; программа не падает. - Передавайте функцию и аргументы в
pcallпо отдельности, а не вызывайте её заранее.