Pakiet programów do zdalnego nauczania Programowania Orientowanego Obiektowo
Dzisiaj jest
Środa, 18 Lipiec 2018
Zarejestrowanych użytkowników: 4
Dostępnych pytań testowych: 102
HOME
Strona tytułowa pracy dyplomowej
NAUKA
Materiały dydaktyczne związane z OOP
TESTY
Sprawdzenie poziomu zdobytej wiedzy
ZASOBY
Literatura i zasoby sieciowe o OOP
ŹRÓDŁA
Zbiór projektów dydaktycznych z OOP
KONTO
Możliwość śledzenia własnych postępów
INFO



Bezpieczeństwo iteratorów

Częstym problemem związanym z używaniem iteratorów jest brak odporności na zewnętrzną modyfikację kontenera. Jeśli jednocześnie iterator jest wykorzystywany do przechodzenia sekwencyjnego przez kontener i kontener jest modyfikowany może dojść do problemów. W najlepszym wypadku pewne elementy kontenera mogłyby być wypisywane dwukrotnie, lub też wybrane elementy nie były by wypisane wcale (wskutek przemieszczeń wewnątrz struktury kontenera). Gorzej jeśli iteratory wskazują na miejsca, które po operacji modyfikującej kontenera nie zawierają już elementów. Jest tak na przykład w przypadku szablonu klas std::vector biblioteki standardowej. Jeśli dynamiczna struktura przechowująca elementy nie jest w stanie pomieścić ich więcej jest kopiowana do większego bloku pamięci, a stary blok zostaje zwolniony. Brak aktualizacji pozycji iteratora po skopiowania do nowego bloku spowoduje, że będzie się on odwoływał do nieodpowiedniego obszaru pamięci.

Istnieje kilka metod zabezpieczeń przed modyfikacją kontenerów. Pierwsza może polegać na tworzeniu głębokiej kopii kontenera w przypadku tworzenia iteratora. Takie rozwiązanie jest jednak bardzo kosztowne, szczególnie jeśli przegląda się duże struktury danych.

Kolejnym rozwiązaniem jest rozpoznawanie sytuacji w której kontener się zmienił. Mógłby on przechowywać składową typu całkowitego, która przy każdej operacji modyfikującej zostawałaby inkrementowana. Podczas tworzenia iterator zapamiętywał by numer ostatnio wykonywanej operacji. Jeśli następnie podczas próby użycia interfejsu iteratora doszło by do wykrycia, że numery operacji w iteratorze i kontenerze różnią się mógłby zostać rzucony wyjątek.

Modyfikacją drugiego rozwiązania mogłoby być użycie wzorca Obserwator (w przypadku iteratorów polimorficznych). W takim wypadku kontener utrzymywał by wewnętrzną strukturę wskaźników z odniesieniami do wszystkich utworzonych iteratorów. Jeśli doszło by do operacji modyfikujących - kontener powiadamiałby o tym fakcie wszystkie obiekty iteratorów. Zaletą w porównaniu do poprzedniej metody jest dodatkowe parametryzowanie powiadomień. W szczególnych przypadkach bowiem mogłyby istnieć iteratory, które mimo zmian w kontenerze były nadal bezpieczne w użyciu. Tylko część iteratorów była by "dezaktywowana", a pozostałe mogłyby dalej poprawnie pracować.

Czwartym rozwiązaniem problemu mogłoby być również oparte na rozwiązaniu drugim. Każdy element kontenera utrzymywał by dwie dodatkowe zmienne: numer operacji w którym element został dodany oraz numer operacji w którym element został usunięty. Iterator na podstawie swojego numeru operacji filtrował by elementy kontenera i dawał dostęp tylko do tych właściwych. Jest to rozwiązanie lepsze od pełnego kopiowania kontenerów, natomiast w dużej części przypadków trudne lub niemożliwe do zaimplementowania (np. w przypadku struktur które utrzymują wewnętrzny porządek, w przypadku drzew binarnych itp). Jednak w przypadku przedstawionego przykładu klasy ModelDanych jest jak najbardziej możliwe.

Adamik Łukasz, Politechnika Śląska w Gliwicach (AEiI) - 2010/11