Wyjątki są zaimplementowane w wielu językach programowania np.
http://pl.wikibooks.org/wiki/C++/Obs%C5%82uga_wyj%C4%85tk%C3%B3w
http://msdn.microsoft.com/en-us/library/6dekhbbc(v=vs.80).aspx
http://php.net/manual/en/language.exceptions.php
http://pl.wikipedia.org/wiki/Wyj%C4%85tek
Wyjątek (ang. exception) jest mechanizmem przepływu sterowania używanym w mikroprocesorach oraz współczesnych językach programowania do obsługi zdarzeń wyjątkowych, a w szczególności błędów, których wystąpienie zmienia prawidłowy przebieg wykonywania programu. W momencie zajścia niespodziewanego zdarzenia generowany jest wyjątek, który musi zostać obsłużony poprzez zapamiętanie bieżącego stanu programu i przejście do procedury jego obsługi. W niektórych sytuacjach po obsłużeniu wyjątku można powrócić do wykonywania przerwanego kodu, korzystając z zapamiętanych informacji stanu. Przykładowo obsługa błędu braku strony pamięci polega najczęściej na pobraniu brakującej strony z pliku wymiany, co umożliwia kontynuowanie pracy programu, natomiast błąd dzielenia przez zero powoduje, że wykonywanie dalszych obliczeń nie ma sensu i musi zostać przerwane na trwałe.
Implementacja w pawn ma pewne ograniczenia ( stąd pseudo 😉 ) wynikające z sposobu jakie są one zaimplementowane.
Nie ma np. wyłapywania nie obsłużonych wyjątków wynika to z tego że implementacja takiego mechanizmu wymagała by użycia np. tasków a takie rozwiązanie było by bardzo podatne na błędy i samo w sobie potrafiło by generować sytuacje wyjątkowe ;).
Radził bym to traktować jaką pewnego rodzaju ciekawostkę ale nic nie stoi na przeszkodzie w używaniu tego w pluginach jednak lepiej przyswoić sobie wiedzę o wyjątkach z źródeł podanych na początku.
Download pliku inc na dole wpisu
Przykłady użycia :
Test1
#include <amxmodx> #include <amxmisc></amxmisc></amxmodx> #include <exceptions.inc></exceptions.inc> #define PLUGIN "New Plugin" #define AUTHOR "DarkGL" #define VERSION "1.0" public plugin_init() { register_plugin(PLUGIN, VERSION, AUTHOR) try(){ testFunction(); } catch("TestExcept"){ new szName[ 256 ], szMessage[ 256 ]; getExceptName( szName , charsmax( szName ) ); getExceptMessage( szMessage, charsmax( szMessage ) ); log_amx( "Print Except '%s' : %s" , szName , szMessage ); } } public testFunction(){ raise("TestExcept","Test Message"); }
Test2: można zagnieżdżać wyjątki
#include <amxmodx> #include <amxmisc></amxmisc></amxmodx> #include <exceptions.inc></exceptions.inc> #define PLUGIN "New Plugin" #define AUTHOR "DarkGL" #define VERSION "1.0" public plugin_init() { register_plugin(PLUGIN, VERSION, AUTHOR) try(){ testFunction(); } catch("TestExcept"){ new szName[ 256 ], szMessage[ 256 ]; getExceptName( szName , charsmax( szName ) ); getExceptMessage( szMessage, charsmax( szMessage ) ); log_amx( "Print Except '%s' : %s" , szName , szMessage ); try(){ testFunction2(); } catch("TestExcept2"){ new szName[ 256 ], szMessage[ 256 ]; getExceptName( szName , charsmax( szName ) ); getExceptMessage( szMessage, charsmax( szMessage ) ); log_amx( "Print Except '%s' : %s" , szName , szMessage ); } } } public testFunction(){ raise("TestExcept","Test Message"); } public testFunction2(){ raise("TestExcept2","Test Message2"); }
Test3: można łapać kilka wyjątkow na raz
#include <amxmodx> #include <amxmisc></amxmisc></amxmodx> #include <exceptions.inc></exceptions.inc> #define PLUGIN "New Plugin" #define AUTHOR "DarkGL" #define VERSION "1.0" public plugin_init() { register_plugin(PLUGIN, VERSION, AUTHOR) try(){ testFunction(); testFunction2(); } catch("TestExcept TestExcept2"){ new szName[ 256 ], szMessage[ 256 ]; getExceptName( szName , charsmax( szName ) ); getExceptMessage( szMessage, charsmax( szMessage ) ); log_amx( "Print Except '%s' : %s" , szName , szMessage ); } } public testFunction(){ raise("TestExcept","Test Message"); } public testFunction2(){ raise("TestExcept2","Test Message2"); }
i tutaj wychodzi pierwsze ograniczenie jeśli obie funkcje zgłoszą wyjątki to zostanie obsłużony tylko drugi czyli TestExcept2 , TestExcept zostanie w pamięci więc jeśli mamy taką sytuację powinniśmy wyczyścić pamieć z tych wyjątków w taki sposób.
poprawna implementacja
#include <amxmodx> #include <amxmisc></amxmisc></amxmodx> #include <exceptions.inc></exceptions.inc> #define PLUGIN "New Plugin" #define AUTHOR "DarkGL" #define VERSION "1.0" public plugin_init() { register_plugin(PLUGIN, VERSION, AUTHOR) try(){ testFunction(); testFunction2(); } catch("TestExcept TestExcept2"){ new szName[ 256 ], szMessage[ 256 ]; getExceptName( szName , charsmax( szName ) ); getExceptMessage( szMessage, charsmax( szMessage ) ); log_amx( "Print Except '%s' : %s" , szName , szMessage ); clearExcepts( "TestExcept TestExcept2" ); } } public testFunction(){ raise("TestExcept","Test Message"); } public testFunction2(){ raise("TestExcept2","Test Message2"); }
lub
#include <amxmodx> #include <amxmisc></amxmisc></amxmodx> #include <exceptions.inc></exceptions.inc> #define PLUGIN "New Plugin" #define AUTHOR "DarkGL" #define VERSION "1.0" public plugin_init() { register_plugin(PLUGIN, VERSION, AUTHOR) try(){ testFunction(); testFunction2(); } catch("TestExcept TestExcept2"){ new szName[ 256 ], szMessage[ 256 ]; getExceptName( szName , charsmax( szName ) ); getExceptMessage( szMessage, charsmax( szMessage ) ); log_amx( "Print Except '%s' : %s" , szName , szMessage ); clearExcept( "TestExcept" ); clearExcept( "TestExcept2" ); } } public testFunction(){ raise("TestExcept","Test Message"); } public testFunction2(){ raise("TestExcept2","Test Message2"); }
jeżeli dwie funkcje zgłaszają ten sam wyjątek też warto to dodać 😉
#include <amxmodx> #include <amxmisc></amxmisc></amxmodx> #include <exceptions.inc></exceptions.inc> #define PLUGIN "New Plugin" #define AUTHOR "DarkGL" #define VERSION "1.0" public plugin_init() { register_plugin(PLUGIN, VERSION, AUTHOR) try(){ testFunction(); testFunction2(); } catch("TestExcept"){ new szName[ 256 ], szMessage[ 256 ]; getExceptName( szName , charsmax( szName ) ); getExceptMessage( szMessage, charsmax( szMessage ) ); log_amx( "Print Except '%s' : %s" , szName , szMessage ); clearExcept( "TestExcept" ); } } public testFunction(){ raise("TestExcept","Test Message"); } public testFunction2(){ raise("TestExcept","Test Message"); }
Kolejne ograniczenie to wywoływanie funkcji catch teoretycznie jeśli funkcja zgłosi wyjątek program powinien przejść od razu do bloku catch jednak nie tutaj. W naszym przypadku catch zostanie uruchomione dopiero gdy wszystkie funkcje w bloku try zostaną wykonane.
Przykład
#include <amxmodx> #include <amxmisc></amxmisc></amxmodx> #include <exceptions.inc></exceptions.inc> #define PLUGIN "New Plugin" #define AUTHOR "DarkGL" #define VERSION "1.0" public plugin_init() { register_plugin(PLUGIN, VERSION, AUTHOR) try(){ testFunction(); testFunction2(); } catch("TestExcept"){ new szName[ 256 ], szMessage[ 256 ]; getExceptName( szName , charsmax( szName ) ); getExceptMessage( szMessage, charsmax( szMessage ) ); log_amx( "Print Except '%s' : %s" , szName , szMessage ); clearExcept( "TestExcept" ); } } public testFunction(){ raise("TestExcept","Test Message"); } public testFunction2(){ //pass }
funkcja testFunction() zgłosi wyjątek mimo to testFuncion2() się wykona dopiero wtedy catch złapie wyjątek
Download