Manejo de errores en Lua
El manejo de errores es necesario durante la ejecución del programa; en operaciones de archivos, transferencia de datos y llamadas a servicios web pueden ocurrir errores inesperados. Si no se presta atención al manejo de la información de errores, esto puede provocar fugas de información, fallos del programa, etc.
En cualquier lenguaje de programación se necesita el manejo de errores. Los tipos de errores son:
- Error de sintaxis
- Error de ejecución
Error de sintaxis
Los errores de sintaxis suelen deberse al uso incorrecto de componentes del programa (como operadores, expresiones). Un ejemplo sencillo es el siguiente:
-- test.lua 文件 a == 2
El resultado de ejecutar el código anterior es:
lua: test.lua:2: syntax error near '=='
Como puedes ver, arriba se produjo un error de sintaxis; un signo "=" es diferente de dos signos "=". Un "=" es una expresión de asignación y dos "=" son una operación de comparación.
Otro ejemplo:
Ejemplo
print(a)
end
Al ejecutar el programa anterior aparecerá el siguiente error:
lua: test2.lua:2: 'do' expected near 'print'
Los errores de sintaxis son más simples que los errores de ejecución; los errores de ejecución no permiten localizar el error específico, mientras que los errores de sintaxis podemos resolverlos rápidamente. Por ejemplo, en el caso anterior solo necesitamos agregar do debajo de la declaración for:
Ejemplo
do
print(a)
end
Error de ejecución
Un error de ejecución ocurre cuando el programa puede ejecutarse normalmente, pero muestra un mensaje de error. Como en el siguiente ejemplo, debido a una entrada incorrecta de parámetros, el programa reporta un error al ejecutarse:
function add(a,b) return a+b end add(10)
Cuando compilamos y ejecutamos el siguiente código, la compilación puede ser exitosa, pero al ejecutarlo se producirá el siguiente error:
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]: ?
En Lua, al llamar a una función, incluso si la lista de argumentos reales no coincide con la lista de parámetros formales, la llamada puede tener éxito; los argumentos sobrantes se descartan y los parámetros faltantes se completan con nil.
El mensaje de error anterior se debe a que, después de que el parámetro b se completó con nil, nil participó en la operación +.
Siadddentro de la función no es"return a+b"sino"print(a,b)"en ese caso, el resultado se convertiría en"10 nil"no se reportaría un error.
Manejo de errores
Podemos usar dos funciones: assert y error para manejar errores. Ejemplo:
Ejemplo
assert(type(a) == "number", "a no es un número")
assert(type(b) == "number", "b no es un número")
return a+b
end
add(10)
Al ejecutar el programa anterior aparecerá el siguiente error:
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 ?
En el ejemplo, assert primero verifica el primer parámetro; si no hay problema, assert no hace nada; de lo contrario, assert lanza el segundo parámetro como mensaje de error.
La función error
Formato de sintaxis:
error (message [, level])
Función: termina la función que se está ejecutando y devuelve el contenido de message como información de error (la función error nunca retorna).
Normalmente, error añade cierta información sobre la ubicación del error al inicio de message.
El parámetro Level indica la ubicación del error a obtener:
- Level=1 [por defecto]: es la ubicación donde se llama a error (archivo + número de línea)
- Level=2: indica la función que llamó a la función que invocó a error
- Level=0: no se añade información de ubicación del error
pcall y xpcall, debug
En Lua, para manejar errores, se puede usar la función pcall (protected call) para envolver el código que necesita ejecutarse.
pcall recibe una función y los argumentos que se le pasarán a esta, y la ejecuta. Resultado de la ejecución: con error o sin error; devuelve true o false, e info de error.
El formato de sintaxis es el siguiente
if pcall(function_name, ….) then -- 没有错误 else -- 一些错误 end
Ejemplo sencillo:
Ejemplo
33
true
> =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 llama al primer argumento en un "modo protegido", por lo que pcall puede capturar cualquier error durante la ejecución de la función.
Generalmente, cuando ocurre un error, se espera obtener más información de depuración, no solo la ubicación del error. Pero cuando pcall retorna, ya ha destruido parte del contenido de la pila de llamadas.
Lua proporciona la función xpcall, que recibe un segundo parámetro: una función de manejo de errores. Cuando ocurre un error, Lua llama a la función de manejo de errores antes de desplegar (unwind) la pila de llamadas, de modo que se pueda usar la biblioteca debug en esta función para obtener información adicional sobre el error.
La biblioteca debug proporciona dos funciones generales de manejo de errores:- debug.debug: proporciona un prompt de Lua para que el usuario examine la causa del error.
- debug.traceback: construye un mensaje de error extendido basado en la pila de llamadas.
>=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
Ejemplo 2 de uso de xpcall:
Ejemplo
n = n/nil
end
function myerrorhandler( err )
print( "ERROR:", err )
end
status = xpcall( myfunction, myerrorhandler )
print( status)
Al ejecutar el programa anterior aparecerá el siguiente error:
ERROR: test2.lua:2: attempt to perform arithmetic on global 'n' (a nil value) falseOtras extensiones