200 likes | 314 Views
Krzysztof Czaiński Opiekun pracy: dr inż. Cezary Stępień. Bezpieczeństwo wyjątków w C++: OpenGL. Motywacja. Dużo literatury o OpenGL The Red Book (Addison-Wesley) http://nehe.gamedev.net/ Dobrze opisane bezpieczeństwo wyjątków w C++ Exceptional C++, Herb Sutter OpenGL i wyjątki?
E N D
Krzysztof Czaiński Opiekun pracy: dr inż. Cezary Stępień Bezpieczeństwo wyjątków w C++: OpenGL Krzysztof Czaiński
Krzysztof Czaiński Motywacja Dużo literatury o OpenGL The Red Book (Addison-Wesley) http://nehe.gamedev.net/ Dobrze opisane bezpieczeństwo wyjątków w C++ Exceptional C++, Herb Sutter OpenGL i wyjątki? GLT ( http://www.nigels.com/glt/ ) Building an OpenGL C++ Class, Dale Rogerson
Krzysztof Czaiński Plan prezentacji Dlaczego wyjątki? Inne sposoby traktowania błędów Bezpieczeństwo wyjątków w C++ Gdzie wstawić bloki try / catch,czy coś więcej? OpenGL, a wyjątki Więcej o bezpieczeństwie wyjątków
Krzysztof Czaiński Obsługa błędów,czyli problem komunikacji Autor klasy (biblioteki) może wykryć błąd, ale nie wie, co z nim zrobić Użytkownik klasy (biblioteki) wie, co zrobić z błędem, lecz nie potrafi go wykryć Źródło: Materiały ZPRdr inż. Robert Nowaka
Krzysztof Czaiński Sposoby traktowania błędów Ignorowanie Zakończenie programu Komunikat dla użytkownika Kod powrotu Zmienna globalna Specjalny stan obiektu Rezerwacja zwracanej wartości Użytkownik może zignorować błąd Kod obsługi wymieszany z innym kodem Obiekt globalny – potencjalne źródło kłopotów Wady Źródło: Materiały ZPRdr inż. Robert Nowaka
Krzysztof Czaiński Mechanizm wyjątków a zasoby void funkcja() { A* a = NULL; try{a = new A; // Kod rzucający delete a; } catch ( ... ) { delete a;throw; } } class A {/*...*/}; void funkcja() { A* a = new A; // Kod rzucający delete a; }
Krzysztof Czaiński Zdobywanie zasobów jest inicjalizacją (RAII) Konstrukcja obiektu jest połączona ze zdobyciem zasobu Destrukcja obiektu jest połączona ze zwolnieniem zasobu Gdy obiekt jest lokalny, zasób jest zwalniany automatycznie w momencie niszczenia obiektu
Krzysztof Czaiński Sprytny wskaźnik template< typename X > class AutoPtr { public: explicit AutoPtr( X* p = NULL ) : p_( p ) {} ~AutoPtr() { delete p_; } X& operator*() const { return *p_; } X* operator->() const { return p_; } private: X* p_; };
Krzysztof Czaiński Użycie sprytnego wskaźnika class A {/*...*/}; void funkcja() { AutoPtr<A> a( new A ); // Kod rzucający a->metoda(); AutoPtr<A> b = a; // ??? }
Krzysztof Czaiński Przykładowy kod z OpenGL void render() { double v[3]; glBegin( GL_TRIANGLES ); for ( int i = 0 ; i < n ; ++i ) { getVertex( i, v ); // rzuca? glVertex3dv( v ); } glEnd(); }
Krzysztof Czaiński Automatyczny glBegin/glEnd struct Begin { explicit Begin( GLenum mode ) { glBegin( mode ); } ~Begin() { glEnd(); } }; #include <boost/utility.hpp> : boost::noncopyable
Krzysztof Czaiński Przykładowy kod z bezpiecznymi wyjątkami void render() { double v[3]; Begin( GL_TRIANGLES ); for ( int i = 0 ; i < n ; ++i ) { getVertex( i, v ); // rzuca? OK. glVertex3dv( v ); } }
Krzysztof Czaiński Przykładowy kod z bezpiecznymi wyjątkami (2) void render() { double v[3]; Beginbegin( GL_TRIANGLES ); for ( int i = 0 ; i < n ; ++i ) { getVertex( i, v ); // rzuca? OK. glVertex3dv( v ); } }
Krzysztof Czaiński Zachowanie stanu OpenGL-a voidselect() { glRenderMode( GL_SELECT ); // kod rzucający int hits = glRenderMode( GL_RENDER ); //... } • Chcemy zagwarantować, żeby po wywołaniu select() OpenGL pozostał w trybie GL_RENDER
Krzysztof Czaiński Automatyczny glRenderMode class RenderMode : boost::noncopyable { public: RenderMode( GLenum mode, GLenum restoreMode ) : restoreMode_(restoreMode), restored_(false) {glRenderMode( mode );} ~RenderMode(){ restoreRenderMode(); } GLint restoreRenderMode() { GLint result = 0; if ( ! restored_ ){ restored_ = true; result = glRenderMode( restoreMode_ ); } return result; } private:GLenum restoreMode_;bool restored_; };
Krzysztof Czaiński Zachowanie stanu OpenGL-az auto- glRenderMode voidselect() { RenderMode x( GL_SELECT, GL_RENDER ); // kod rzucający int hits = x.restoreRenderMode(); //... }
Krzysztof Czaiński Co to znaczybezpieczeństwo wyjątków? Gwarancje bezpieczeństwa wyjątkówwg Dave’a Abrahama: Podstawowa: Brak wycieku zasobów Wszystkie obiekty pozostają w stanie używalnym, ale nie koniecznie przewidywalnym Silna: Gdy wystąpi wyjątek, stan programu pozostaje niezmieniony Nothrow: Nigdy nie rzuca Źródło: GotW #61
Krzysztof Czaiński Korzyści Programowanie bezpieczne z uwzględnieniem wyjątków ma istotne zalety: Użytkownik klasy (biblioteki) może używać mechanizmu wyjątków Wyjątki nie zakłócą pracy programu W razie niespodziewanego błędu (np. braku pamięci) program może działać dalej Wszelkie zasoby zostają zwolnione mimo wyjątku Unikamy nie zwolnienia zasobów przez nieuwagę Zasoby są zwalniane automatycznie
Krzysztof Czaiński Bezpieczeństwo wyjątkówa etap projektowania template < typename T > class Stack { public: T pop(); // ... private: T* tab_; size_t size_; }; template < typename T > T Stack<T>::pop() { // assert( size_ > 0 ); return tab_[--size_]; } template < typename T > T Stack<T>::pop() { // assert( size_ > 0 ); T result( tab_[size_-1] ); --size_; return result; } template < typename T > void Stack<T>::pop( T& result ) { // assert( size_ > 0 ); result = tab_[size_-1]; --size_; }
Krzysztof Czaiński Podsumowanie Warto pisać kod w C++ uwzględniając wyjątki i warto uwzględnić to już na etapie projektowania. Dla zainteresowanych polecam: ZPR, dr inż. Robert Nowak http://www.gotw.ca/gotw/