English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Tratamento de Erros do Lua

O tratamento de erros durante a execução do programa é necessário, pois ao realizarmos operações de arquivo, transferência de dados e chamadas de web service, podem ocorrer erros inesperados. Se não prestar atenção ao tratamento das mensagens de erro, pode ocorrer vazamento de informações, falha no funcionamento do programa e outros problemas.

Em qualquer linguagem de programação, é necessário lidar com erros. Tipos de erros incluem:

  • Erro de sintaxe

  • Erro de execução

Erro de sintaxe

Erros de sintaxe geralmente ocorrem devido ao uso incorreto dos componentes do programa (como operadores, expressões). Um exemplo simples é o seguinte:

-- arquivo test.lua
a == 2

O resultado da execução do código acima é:

lua: test.lua:2: erro de sintaxe perto de '=='

Como você pode ver, acima ocorreu um erro de sintaxe, um "=" e dois "=" têm diferenças. Um "=" é uma expressão de atribuição e dois "=" são operações de comparação.

Outro exemplo:

for a= 1,10
   print(a)
end

A execução do programa acima resultará no seguinte erro:

lua: test2.lua:2: 'do' esperado perto de 'print'

Erros de sintaxe são mais simples do que erros de execução, erros de execução não podem localizar o erro específico, enquanto erros de sintaxe podem ser resolvidos rapidamente, como no exemplo acima, apenas adicionamos 'do' na instrução 'for':

for a= 1,10
do
   print(a)
end

Erro de execução

O erro de execução é que o programa pode ser executado normalmente, mas gerará mensagens de erro. O exemplo a seguir, devido ao erro de entrada de parâmetros, o programa gerará um erro ao executar:

function add(a,b)
   return a+b
end
add(10)

Quando compilamos e executamos o seguinte código, a compilação pode ser bem-sucedida, mas ao executar, ocorrerá o seguinte erro:

lua: test2.lua:2: tentativa de realizar operação aritmética em local 'b' (um valor nil)
stack traceback:
    test2.lua:2: in function 'add'
    test2.lua:5: no bloco principal
    [C]: ?

no lua, ao chamar uma função, mesmo que a lista de argumentos e a lista de parâmetros não sejam consistentes, ainda pode ser chamada com sucesso, os argumentos em excesso serão descartados e os parâmetros faltantes serão substituídos por nil.

A mensagem de erro acima ocorre porque o parâmetro b foi substituído por nil e nil participou da + operação.

supondo add dentro da função não é "return a"+b" em vez de "print(a,b)" se assim for, o resultado será "10 nil Não gerará erro.

Tratamento de erros

Podemos usar duas funções: assert e error para lidar com erros. Exemplo a seguir:

local function add(a,b)
   assert(type(a) == "number", "a não é um número")
   assert(type(b) == "number", "b não é um número")
   return a+b
end
add(10)

A execução do programa acima resultará no seguinte erro:

lua: test.lua:3: b não é um número
stack traceback:
    [C]: in function 'assert'
    test.lua:3: in local 'add'
    test.lua:6: no bloco principal
    [C]: no ?

No exemplo, o assert primeiro verifica o primeiro parâmetro, se não houver problema, o assert não faz nada; caso contrário, o assert lança uma exceção com o segundo parâmetro como mensagem de erro.

Função error

Formato de sintaxe:

error (mensagem [, level])

Função: Termina a função em execução e retorna o conteúdo da mensagem como mensagem de erro (a função error nunca retorna)

Normalmente, o error adiciona algumas informações de localização do erro ao cabeçalho da mensagem.

O parâmetro Level indica a localização do erro:

  • Level=1[Padrão]: Para a localização da chamada error (arquivo+número da linha)

  • Level=2: Indica qual função chamou error

  • Level=0: Não adiciona informações de localização do erro

pcall e xpcall, debug

No Lua, para lidar com erros, pode-se usar a função pcall (chamada protegida) para embalar o código a ser executado.

O pcall recebe uma função e os parâmetros a serem passados para essa função, e a executa. O resultado da execução é: com erro, sem erro; retorna true ou false, errorinfo.

Formato de sintaxe:

if pcall(function_name, ... ) then
-- Nenhum erro
else
-- Alguns erros
end

Exemplo simples:

> =pcall(function(i) print(i) end, 33)
33
true
   
> =pcall(function(i) print(i) error('error..') end, 33)
33
false stdin:1: error..

Aqui, note a lógica de julgamento do valor de retorno:

> function f() return false,2 end
> if f() then print '1'else print '0' end
0

O pcall chama o primeiro parâmetro em um modo "protegido", portanto, o pcall pode capturar qualquer erro que ocorra durante a execução da função.

Normalmente, quando um erro ocorre, desejamos obter mais informações de depuração do que apenas o local onde o erro ocorreu. No entanto, quando o pcall retorna, ele já destruiu parte do pilha de chamadas.

Lua oferece a função xpcall, que recebe como segundo parâmetro um função de tratamento de erros. Quando um erro ocorre, o Lua chama essa função de tratamento de erros antes de desempilhar a pilha de chamadas, permitindo que se use a biblioteca debug para obter informações adicionais sobre o erro.

A biblioteca debug fornece duas funções de tratamento de erros genéricas:

  • debug.debug: fornece um prompt Lua para que o usuário verifique a causa do erro

  • debug.traceback: constrói uma mensagem de erro ampla com base na pilha de chamadas

>=xpcall(function(i) print(i) error('error..') end, function() print(debug.traceback()) end, 33)
33
stack traceback:
stdin:1: no função <stdin:1>
[C]: no função 'error'
stdin:1: no função <stdin:1>
[C]: no função 'xpcall'
stdin:1: no bloco principal
[C]: no ?
false nil

Exemplo de uso do xpcall 2:

function myfunction()
   n = n/nil
end
function myerrorhandler( err )
   print( "ERROR:", err )
end
status = xpcall( myfunction, myerrorhandler )
print( status )

A execução do programa acima resultará no seguinte erro:

ERROR:2.lua:2: tentativa de realizar operação aritmética no global 'n' (um valor nulo)
false