Lua - Obsługa błędów

Potrzeba obsługi błędów

Obsługa błędów jest dość krytyczna, ponieważ operacje w świecie rzeczywistym często wymagają użycia złożonych operacji, które obejmują operacje na plikach, transakcje w bazie danych i wywołania usług internetowych.

W każdym programowaniu zawsze wymagana jest obsługa błędów. Błędy mogą być dwojakiego rodzaju, w tym:

  • Błędy składniowe
  • Błędy czasu wykonywania

Błędy składniowe

Błędy składniowe występują z powodu niewłaściwego użycia różnych składników programu, takich jak operatory i wyrażenia. Poniżej przedstawiono prosty przykład błędu składniowego.

a == 2

Jak wiesz, istnieje różnica między używaniem pojedynczego „równego” i podwójnego „równego”. Używanie jednego zamiast drugiego może prowadzić do błędu. Jedno „równe” odnosi się do przypisania, a podwójne „równe” odnosi się do porównania. Podobnie mamy wyrażenia i funkcje, które mają predefiniowane sposoby implementacji.

Kolejny przykład błędu składniowego pokazano poniżej -

for a= 1,10
   print(a)
end

Po uruchomieniu powyższego programu otrzymamy następujące dane wyjściowe -

lua: test2.lua:2: 'do' expected near 'print'

Błędy składniowe są znacznie łatwiejsze w obsłudze niż błędy czasu wykonania, ponieważ interpreter Lua lokalizuje błąd wyraźniej niż w przypadku błędu wykonania. Z powyższego błędu, możemy łatwo wiedzieć, że dodanie zrób oświadczenia przed instrukcja print jest wymagane zgodnie strukturze Lua.

Błędy czasu wykonywania

W przypadku błędów w czasie wykonywania program wykonuje się pomyślnie, ale może to skutkować błędami w czasie wykonywania z powodu błędów w danych wejściowych lub nieprawidłowej obsługi funkcji. Poniżej przedstawiono prosty przykład pokazujący błąd czasu wykonywania.

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

add(10)

Kiedy budujemy program, będzie się on budował i działał. Po uruchomieniu wyświetla błąd czasu wykonywania.

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]: ?

Jest to błąd w czasie wykonywania, który wystąpił z powodu nieprzekazywania dwóch zmiennych. Plikb jest oczekiwany i tutaj jest zerowy i powoduje błąd.

Funkcje asertu i błędu

Aby poradzić sobie z błędami, często używamy dwóch funkcji - assert i error. Poniżej przedstawiono prosty przykład.

local function add(a,b)
   assert(type(a) == "number", "a is not a number")
   assert(type(b) == "number", "b is not a number")
   return a+b
end

add(10)

Kiedy uruchomimy powyższy program, otrzymamy następujące wyjście błędu.

lua: test2.lua:3: b is not a number
stack traceback:
	[C]: in function 'assert'
	test2.lua:3: in function 'add'
	test2.lua:6: in main chunk
	[C]: ?

Plik error (message [, level])kończy ostatnią wywołaną funkcję chronioną i zwraca komunikat jako komunikat o błędzie. Ten błąd funkcji nigdy nie powraca. Zwykle komunikat o błędzie dodaje pewne informacje o pozycji błędu na początku wiadomości. Argument poziomu określa, w jaki sposób uzyskać pozycję błędu. Przy poziomie 1 (domyślnym) pozycja błędu jest miejscem wywołania funkcji błędu. Poziom 2 wskazuje błąd w miejscu wywołania funkcji, która wywołała błąd; i tak dalej. Przekazanie poziomu 0 pozwala uniknąć dodawania informacji o pozycji błędu do komunikatu.

pcall i xpcall

W programowaniu Lua, aby uniknąć wyrzucania tych błędów i obsługi błędów, musimy użyć funkcji pcall lub xpcall.

Plik pcall (f, arg1, ...)function wywołuje żądaną funkcję w trybie chronionym. Jeśli jakiś błąd wystąpi w funkcji f, nie zgłasza błędu. Po prostu zwraca stan błędu. Poniżej przedstawiono prosty przykład użycia pcall.

function myfunction ()
   n = n/nil
end

if pcall(myfunction) then
   print("Success")
else
	print("Failure")
end

Kiedy uruchomimy powyższy program, otrzymamy następujące dane wyjściowe.

Failure

Plik xpcall (f, err)funkcja wywołuje żądaną funkcję, a także ustawia procedurę obsługi błędów. Żaden błąd wewnątrz f nie jest propagowany; zamiast tego xpcall wychwytuje błąd, wywołuje funkcję err z oryginalnym obiektem błędu i zwraca kod stanu.

Poniżej przedstawiono prosty przykład dla xpcall.

function myfunction ()
   n = n/nil
end

function myerrorhandler( err )
   print( "ERROR:", err )
end

status = xpcall( myfunction, myerrorhandler )
print( status)

Kiedy uruchomimy powyższy program, otrzymamy następujące dane wyjściowe.

ERROR:	test2.lua:2: attempt to perform arithmetic on global 'n' (a nil value)
false

Jako programista najważniejsze jest zadbanie o właściwą obsługę błędów w programach, które piszesz. Korzystanie z obsługi błędów może zapewnić obsługę nieoczekiwanych warunków wykraczających poza warunki brzegowe bez przeszkadzania użytkownikowi programu.