Rozdział 5
Zarządzanie pamięcią
Zarządzanie pamięcią
AutoCAD został zaprojektowany w taki sposób, by w razie potrzeby automa-
tycznie dostosowywał się do ilości wolnej pamięci. I chociaż niektóre systemy
o ograniczonej wielkości pamięci mogą wymagać dostrojenia, to jednak wię-
kszość użytkowników nie będzie musiała korzystać z informacji umieszczo-
nych w tym rozdziale.
Wszystkie opisywane w tym podręczniku funkcje definiowane przez użyt-
kownika i funkcje standardowe są przechowywane w pamięci komputera
tylko w czasie trwania sesji edycyjnej AutoCAD-a. W celu uruchomienia
AutoLISP-u konieczne jest wydzielenie dla niego dwóch dużych obszarów
pamięci. Pierwszy z nich, zwany stertą (ang. heap), służy do przechowywa-
nia wszystkich funkcji i symboli (zwanych także węzłami); im więcej symboli
i funkcji jest w użyciu (i im bardziej funkcje te są złożone), tym większy ob-
szar sterty będzie wykorzystywany. W drugim obszarze pamięci, zwanym
stosem (ang. stack), przechowywane sÄ… argumenty funkcji oraz wyniki dzia-
łań pośrednich. Im głębiej funkcje zostały zagnieżdżone, lub im więcej wy-
konują one operacji rekurencyjnych, tym większy obszar stosu jest potrzebny.
Obszar węzłów
Węzeł jest strukturą pamięci, która może reprezentować daną AutoLISP-u
dowolnego typu. Aktualnie AutoLISP wykorzystuje węzły o długości 12 baj-
tów. W celu uniknięcia nadmiernego rozdrobnienia pamięci i ułatwienia za-
rządzania stertą, węzły są w stercie powiązane w grupy zwane segmentami.
Standardowo segment zawiera 514 węzłów (6168 bajtów).
AutoLISP prowadzi wykaz wolnych węzłów (tzn. takich węzłów, które aktu-
alnie nie są związane z żadnym symbolem). Gdy potrzebny jest węzeł do
przechowywania symbolu lub wartości, AutoLISP przegląda tę listę w poszu-
kiwaniu dostępnego wolnego węzła. Jeżeli nie ma takiego, to automatycznie
wykonywany jest proces porządkowania, powodujący umieszczenie na liście
wolnych węzłów tych, które aktualnie nie są powiązane z symbolami. Jeden
z nich zostanie potem automatycznie wybrany, stosownie do potrzeb.
Jeżeli w wyniku takiego porządkowania odzyska się zbyt mało węzłów, to
AutoLISP sięgnie po dodatkowy segment ze sterty. Jeżeli mu się to uda, nowe
węzły zostaną wpisane na listę wolnych a jeden z nich zostanie wybrany
zgodnie z zapotrzebowaniem. Jeżeli z obszaru sterty nie można uzyskać do-
Zarządzanie pamięcią 197
Zarządzanie pamięcią
datkowego segmentu, to wywoływany jest mechanizm wirtualnego stronico-
wania funkcji, który powoduje uwolnienie pewnych węzłów przez wyrzuce-
nie z pamięci najdawniej wykorzystywanej funkcji. W przeciwnym razie ge-
nerowany jest komunikat zbyt mały obszar węzłów i funkcja wymagająca ob-
szaru węzłów nie jest wykonywana. Należy pamiętać o tym, że obszar wę-
złów nigdy nie jest zwracany do sterty przed zakończeniem pracy AutoCAD-a.
Porządkowanie węzłów można wymusić za pomocą funkcji gc:
(gc)
Należy pamiętać o tym, że operacje takie są bardzo czasochłonne i nie po-
winny być uruchamiane bez potrzeby. Najlepiej jest pozostawić je automa-
tycznie uruchamianemu mechanizmowi AutoCAD-a, który powoduje ich wy-
konywanie tylko wtedy, gdy jest to konieczne.
Odzyskiwanie obszaru węzłów
Często okazuje się, że utworzone funkcje i symbole AutoLISP-u są potrzebne
tylko na krótką chwilę. Po wykorzystaniu, gdy nie są już dalej przydatne,
wskazane jest usunięcie ich definicji przez przypisanie im nil. Przykładowo,
jeżeli wczytana i wykorzystana funkcja o nazwie parametry nie jest już po-
trzebna, to można się jej pozbyć wprowadzając:
(setq parametry nil)
Po przypisaniu funkcji wartości nil, zajmowany przez nią obszar węzłów zo-
stanie zwolniony i będzie mógł być wykorzystany przez inne funkcje i sym-
bole.
Chcąc odzyskać obszar węzłów wykorzystywany przez symbol typu FILE
(otrzymywany w wyniku funkcji open), należy przed przypisaniem mu war-
tości nil zamknąć związany z nim plik za pomocą funkcji close. Jednocześ-
nie otwarta może być tylko ograniczona liczba dojść do plików i zaniechanie
ich zamknięcia powoduje, że otwarte dojścia do zbędnych obecnie plików
ograniczają liczbę nowych plików, które mogą zostać otworzone.
Uwaga: W wydaniach poprzedzających Wydanie 12, AutoCAD przechowywał
listÄ™ wszystkich zdefiniowanych symboli i funkcji pod symbolem atomlist. Lista
ta nie jest już przechowywana w ten sposób, stąd "wycięcie listy atomów" nie
jest obecnie stosowaną metodą usuwania z pamięci funkcji i symboli. W dal-
szym ciągu jednak można odczytać listę funkcji i symboli, używając funkcji
atoms-famiły:
(atoms-famiły 0)
Funkcja ta może być wykorzystywana do uzyskiwania listy zdefiniowanych
właśnie symboli. Dalsze informacje na temat funkcji atoms-famiły zawiera
rozdział 4.
Uwagi techniczne
Uwaga: Informacje przedstawione poniżej mogą być wykorzystane jedynie
przez programistów zaawansowanych w używaniu języka LISP. Początkują-
cy programiści mogą (i powinni) pominąć przedstawione tu rozważania. Roz-
dział ten opisuje wewnętrzne mechanizmy AutoLISP-u, które bez uprzedze-
nia mogÄ… ulec zmianie.
198 Zarządzanie pamięcią
Rozdział5
Informacja o wykorzystaniu pamięci
Funkcja mem:
(mem)
wyświetla aktualny stan pamięci AutoLISP-u i zwraca nil. Parametr Nodes:
określa całkowitą liczbę przydzielonych do tej pory węzłów, która powinna
być równa iloczynowi wielkości segmentu węzłów i liczby węzłów w segmen-
cie. Free nodes: oznaczają liczbę węzłów, które są aktualnie na liście wolnych
węzłów, umieszczonych tam w procesie porządkowania. Pozycja Segments:
podaje liczbę przydzielonych segmentów węzłów, a Alocate: podaje aktualny
rozmiar segmentu. Collections: jest liczbą operacji porządkowania węzłów
(zarówno uruchamianych automatycznie, jak i w sposób wymuszony).
Obszar łańcuchów alfanumerycznych
Obszar pamięci przeznaczony dla łańcuchów alfanumerycznych korzysta
z tej samej sterty co segmenty węzłów. Jeżeli w celu przeznaczenia całej do-
stępnej pamięci na obszar węzłów, program wywołuje opisywane dalej fun-
kcje, służące do przydzielania pamięci przez użytkownika, to bardzo prawdo-
podobne jest otrzymanie komunikatu zbyt mały obszar łańcuchów. Ma to
równie nieprzyjemne skutki, jak zbyt mały obszar węzłów. Dobrze jest po-
zwolić na to, aby przydział pamięci dla węzłów odbywał się automatycznie.
Zwykle zapewnia to pozostawienie dostatecznie dużego obszaru łańcuchów.
Obszar łańcuchów wykorzystywany jest do wszystkiego, począwszy od nazw
symboli do tekstów zgłoszeń gotowości i tekstów menu, które są przekazy-
wane do ewaluacji przez AutoLISP. Jeżeli wykorzystywane są długie pozycje
menu, zawierające podlegające wartościowaniu wyrażenia AutoLISP-u, to
będą one wymagały znaczącej ilości ciągłych obszarów łańcuchów ze sterty.
Przechowywanie symboli
Struktura pamięci AutoLISP-u charakteryzuje się intensywnym wykorzy-
stywaniem operacji na typach wskaźnikowych. Wszystko jest reprezentowa-
ne w strukturze węzłów i zapotrzebowanie na węzły jest bardzo duże. Proste
przypisanie wartości symbolowi:
(setq longsymbol 3.1415)
wymaga trzech węzłów: jednego na zapamiętanie położenia na liście ATOM-
LIST, drugiego na przechowanie nazwy symbolu i trzeciego na przechowanie
jego wartości. Jeżeli nazwa symbolu składa się z sześciu lub mniejszej ilości
znaków, to jest ona zapamiętana bezpośrednio w węźle nazwy symbolu.
W przeciwnym razie, nazwa symbolu jest przechowywana w obszarze łań-
cuchów, przydzielonym specjalnie do tego celu ze sterty. Węzeł nazwy sym-
bolu będzie wtedy wskazywać ten łańcuch. Reasumując, używanie krótkich
nazw symboli (sześć lub mniej znaków) redukuje wymagania w zakresie roz-
miaru obszaru łańcuchów i powoduje mniej podziałów sterty.
Zarządzanie pamięcią 199
Zarządzanie pamięcią
Sterowanie przydziałem pamięci
Funkcje alloc oraz expand mogą zostać użyte przez programistę do bezpo-
średniego sterowania przydziałem pamięci dla obszarów węzłów i łańcu-
chów. W ten sposób można zwiększać efektywność tworzonych programów
użytkowych. Użycie tych wyrażeń na początku pliku acad.lsp pozwala na
wstępne przydzielenie obszaru węzłów oraz na zarezerwowanie pewnego ob-
szaru łańcuchów. Można dzięki temu zredukować liczbę potrzebnych opera-
cji porządkowania węzłów, co poprawia szybkość działania programu.
Funkcja alloc umożliwia zmianę rozmiaru wymaganego przez następne seg-
menty na inny niż 514 węzłów.
(alloc numbet)
Funkcja alloc ustala liczony w węzłach rozmiar segmentu na określony
przez argument number i zwraca jego poprzednią wartość.
Funkcja expand umożliwia sterowanie rozmiarem przydzielanego obszaru
węzłów przez podanie wymaganej liczby segmentów.
(expand numbel)
Argument liczba określa liczbę segmentów, która ma zostać przydzielona.
Funkcja expand zwraca liczbę segmentów, którą mogła pobrać ze sterty. Mo-
że się ona okazać znacznie mniejsza od wymaganej, w zależności od wielkości
pozostałego jeszcze w stercie obszaru.
Przykład:
(alloc 1024)
ustala rozmiar segmentu na 1024 węzły, co wymaga 12,488 bajtów pamięci sterty
na każdy segment.
(alloc 100)
ustala rozmiar segmentu na 100. Wymagane jest tu tylko 1200 bajtów na
segment.
Jeżeli rozmiar segmentu ma standardową wartość 512 węzłów, to wywoła-
nie:
(expand 10)
żąda 10 segmentów (61480 bajtów). Nic nie stoi na przeszkodzie, by zażądać
więcej.
Niżej przedstawiono przykład praktyczny:
(alloc 3000) Ustalenie rozmiaru segmentu na 3000 węzłów
(expand 1) Pobranie 3000 wolnych węzłów (l segment)
(alloc 10000) Ustala duży rozmiar segmentu, co zapobiegnie doda-
waniu następnych.
To wywołanie rezerwuje 36,000 bajtów na obszar węzłów, pozostawiając re-
sztę sterty na obszar łańcuchów. Węzły te zostaną wstępnie przydzielone
i umieszczone na liście wolnych do wykorzystania. Oznacza to, że proces po-
rządkowania nie będzie potrzebny tak długo, jak długo nie zostanie użytych
więcej niż 3000 węzłów. Będzie to oczywiście miało miejsce po wykorzystaniu
200 Zarządzanie pamięcią
Rozdziała
wszystkich węzłów, tak aby mogły zostać zaspokojone dalsze potrzeby. Wy-
rażenie (alloc 10000) ustanawia taki rozmiar segmentu, który zapobiega
przydzielaniu ze sterty dodatkowych segmentów. Pozostała część sterty bę-
dzie zatem zarezerwowana na łańcuchy alfanumeryczne.
Jeżeli zastosuje się strategię przeciwną, która polega na stopniowym zmniej-
szaniu rozmiaru segmentu, aż do momentu, gdy żądanie jednego węzła nie
będzie mogło zostać zaspokojone (tzn. "(alloc 1) (expand 1)" zwróci 0), to cała
sterta zostanie wykorzystana na obszar węzłów i doprowadzi to do błędu
zbyt maty obszar łańcuchów. Takie postępowanie nie jest zalecane. Bez do-
stępu do obszaru łańcuchów AutoLISP staje się bezużyteczny.
Wirtualne stronicowanie funkcji
Wirtualne stronicowanie funkcji może zajść jedynie w wypadku, gdy wszy-
stkie pozostałe rodzaje pamięci wirtualnej zostaną wyczerpane. Na większo-
ści platform zdarza się to rzadko. Funkcja vmon została pozostawiona w celu
zachowania zgodności z poprzednimi wersjami AutoLISP-u.
Gdy program napisany w AutoLISP-ie stanie się zbyt duży, by zmieścić się
w dostępnym obszarze węzłów, można uruchomić mechanizm wirtualnego
stronicowania funkcji, pozwalający na dalsze powiększanie programu. Osią-
ga się to przez wykonanie funkcji vmon przed pierwszym wywołaniem
w programie funkcji defun:
(vmon)
Powoduje to uaktywnienie wirtualnego stronicowania funkcji na pozostałą
część sesji rysunkowej. Po włączeniu, stronicowanie funkcji nie może zostać
wyłączone. Stronicowaniu podlegają wyłącznie funkcje utworzone za pomo-
cą defun po wywołaniu funkcji vmon, tak więc definicje funkcji defun utwo-
rzone przed wywołaniem vmon nie będą stronicowane i w dalszym ciągu mo-
gą spowodować wyświetlenie komunikatu błędu zbyt mały obszar węzłów
i zakończenie działania programu.
Po wykonaniu funkcji vmon, przekroczenie przez AutoLISP dostępnego
obszaru węzłów powoduje wyrzucenie z pamięci rzadko używanych fun-
kcji i w razie potrzeby wczytanie ich na powrót. Nie trzeba zajmować się
tym mechanizmem, gdyż jest to proces w pełni automatyczny i niewido-
czny dla programu. Funkcje są wyrzucane z pamięci do pliku tymczaso-
wego, obsługiwanego przez mechanizm stronicowania AutoCAD-a.
System pamięci wirtualnej stronicuje tylko funkcje. Oznacza to, że konieczne
jest posiadanie wystarczającego obszaru węzłów do przechowywania wszy-
stkich list danych, nazw funkcji i nazw zmiennych, wykorzystywanych przez
program.
Gdy funkcja vmon jest aktywna, funkcja mem wyświetla dwa dodatkowe po-
la. Swap-ins: podaje liczbÄ™ funkcji wczytanych z pliku, utworzonego na po-
trzeby mechanizmu stronicowania. SÄ… to funkcje stronicowane, wczytane
z pliku stron w wyniku zgłoszenia takiej potrzeby przez zwykłe wywołanie
funkcji. Pozycja Page file: ukazuje rozmiar pliku stron, utworzonego w celu
przechowywania funkcji, usuwanych z pamięci w efekcie działania mecha-
nizmu stronicowania.
Po wykonaniu funkcji vmon, wszystkie definicje defun umieszczajÄ… na po-
czątku listy każdej funkcji nowy węzeł o nazwie tabliczka strony. Węzeł ten
jest dodawany przed listą zawierającą argumenty formalne. Węzły te są
Zarządzanie pamięcią 201
Zarządzanie pamięcią
przeznaczone wyłącznie do wykorzystywania przez mechanizm stronicowa-
nia i nie powinny być w żaden sposób zmieniane przez programy użytkowe.
W przypadku tych węzłów funkcja type zwraca PAGETB.
Kiedy AutoLISP wypełni wszystkie węzły, najrzadziej wykorzystywana fun-
kcja jest usuwana z pamięci i zapisywana do pliku stronicowania, a adres
pliku jest umieszczany w tabliczce strony. Wszystkie pozostałe węzły funkcji
są uwalniane. Tabliczka strony zostaje oznakowana, wskazując że funkcja
została przeniesiona do pliku. W sytuacji, gdy przeniesiona na zewnątrz fun-
kcja jest wartościowana, musi przedtem nastąpić jej ponowne wczytanie
z pliku stronicowania (może przy tym dojść do przeniesienia na zewnątrz in-
nych funkcji). Jeżeli funkcja była już raz zapisana w pliku stronicowania, to
kolejne jej przeniesienie na zewnątrz zwalnia po prostu jej węzły: nie ma
wówczas potrzeby powtórnego zapisywania jej w pliku, gdyż ona ciągle
w pliku istnieje.
W języku AutoLISP, funkcje utworzone z użyciem defun są w istocie listami
i mogą być wykonywane na nich takie same operacje, jak na innych listach.
Programy wykonujące takie operacje muszą uwzględniać operacje mechani-
zmu stronicowania (lub nie powinny nigdy korzystać z funkcji vmon). Prze-
de wszystkim, funkcje utworzone przez defun zawierają na początku węzeł
tabliczki strony, który powinien zostać pominięty w trakcie przeszukiwania
listy. Jeżeli funkcję utworzono jako listę z pominięciem defun, to będzie ona
pracowała poprawnie, ale nie będzie podlegała operacjom stronicowania. Je-
żeli będzie to często stosowane, można łatwo doprowadzić do przekroczenia
pamięci. Dla odmiany można zablokować funkcję w pamięci w wyniku prze-
definiowaniajej bez tabliczki strony. Przykładowo, w celu trwałego ulokowa-
nia w pamięci zdefiniowanej przez defun funkcji o nazwie aplikom można
użyć wyrażenia:
(setq aplikom (cdr aplikom))
które spowoduje usunięcie znajdującej się na początku listy tabliczki strony.
W trakcie wydruku funkcji przy użyciu print, tabliczki stron są drukowane
jako spacje. Obecność spacji po pierwszym lewym nawiasie świadczy więc
o tym, że funkcja może podlegać operacji stronicowania.
W przypadku funkcji przerzuconej na zewnątrz, próba przeszukiwania fun-
kcji tak jakby była listą danych, spowoduje odszukanie tylko tabliczki strony.
Uzyskanie dostępu do funkcji nie powoduje wrzucenia jej do wewnątrz - takie
wczytanie może spowodować tylko ewaluacja funkcji. Jeżeli więc funkcje są
tworzone i modyfikowane na bieżąco, to należy budować je jako listy, nie ko-
rzystając z funkcji defun. Można też wykorzystać opisany wyżej sposób blo-
kowania funkcji w pamięci.
Właściwe techniki programowania
W tej części przedstawione są pewne techniki programowania, przydatne za-
równo początkującym, jak i zaawansowanym programistom w AutoLISP-ie.
Nie jest ona pomyślana jako ćwiczenia wprowadzające. Szereg pozycji bib-
liograficznych na temat języka programowania LISP wymieniono we wstę-
pie na stronie l.
Właściwe techniki programowania
Rozdział 5
Ogólna organizacja kodu programu
Metody zorganizowania komentarzy i wcięć w kodzie programu są pozosta-
wione całkowicie do uznania użytkownika. Służą one wyłącznie jako pomoc
dla programisty i końcowego użytkownika i nie mają wpływu na sam kod.
Jeśli byłoby to przydatne, możliwe jest utworzenie oryginalnego standardu
dla siebie lub grupy współprogramistów, tak by tworzony kod zachował od-
rębny styl i wyglądał profesjonalnie.
Komentarze
Korzystanie z komentarzy w kodzie programu jest bardzo istotne. SÄ… one
przydatne dla programisty i dla przyszłego użytkownika, który może być
zmuszony do dostosowania programu do własnych potrzeb przez zmianę czę-
ści jego kodu. Komentarzem w AutoLISP-iejest wszystko, co występuje w li-"
nii po średniku (;). Komentarze mogą być wykorzystywane na przykład w na-
stępujących celach:
• do nadawania tytułów, podawania autora lub daty utworzenia,
• podawania instrukcji użytkowania programu,
• podawania uwag objaÅ›niajÄ…cych wewnÄ…trz kodu procedury
• umieszczania osobistych notatek podczas uruchamiania programu
• wstawiania znaków poprawiajÄ…cych estetykÄ™ kodu programu.
Obfite komentowanie kodu źródłowego podczas pisania programów
w AutoLISP-iejest pracą, która sowicie się opłaca. Jednakowo użyteczne są
komentarze blokowe (zajmujące całe wiersze), jak i komentarze wplatane
(czyli komentarze występujące po średniku w tej samej linii programu,
w której występuje wyrażenie AutoLISP-u). Programujący w AutoLISP-ie
dopracowali się pewnej roboczej konwencji dla każdej klasy komentarzy
(przykłady podaje Guy L. Steele Jr., w podręczniku "Common LISP"). Nie-
które pliki .Isp, dostarczane z AutoCAD-em (ale nie wszystkie!), są także do-
brym przykładem stylu komentowania programów w AutoLISP-ie. W szcze-
gólności plik ai_utils.lsp jest bardzo bogato skomentowany i zawiera szereg
ciekawych i przydatnych w AutoLISP-ie procedur.
Podczas tworzenia własnego stylu komentowania należy pamiętać o nastę-
pujÄ…cych zaleceniach:
• Opisowa część nagłówka może objaÅ›niać sposób korzystania z pliku na ty-
le dokładnie, by nie zachodziła konieczność sięgania do innej dokumen-
tacji.
• Ilość Å›redników, poprzedzajÄ…cych komentarz oraz umiejscowienie komen-
tarza w pliku, mogą wskazywać na znaczenie i zawartość komentarza.
• Wiele monitorów potrafi pokazać jedynie 80 kolumn tekstu. Komentarz
rozpoczynający się w kolumnie 81 może nie być widoczny na ekranie.
Reguły języka są bardzo elastyczne, a dużo ważniejsze jest podawanie ko-
mentarzy, niż przestrzeganie jakichkolwiek umownych konwencji dotyczą-
cych ich rozkładu.
Właściwe techniki programowania 203
Zarządzanie pamięcią
Wcięcia i wyrównywanie tekstu
Intensywne korzystanie przez AutoLISP z nawiasów może sprawiać trud-
ność w czytaniu jego kodu. Tradycyjną techniką zwalczania tej przykrej ce-
chy jest stosowanie wcięć. Polega to na takim rozplanowaniu kodu progra-
mu, że im bardziej zagnieżdżona jest dana linia kodu, tym dalej odsunięta
jest od lewego marginesu. Ilość poziomów nawiasów jest tak duża, że najczę-
ściej stosowany standard wcięć przesuwa każdą linię następnego poziomu
tylko o dwie spacje w prawo, w przeciwieństwie do najczęściej stosowanej
konwencji dla programowania w języku C, w której każdy poziom jest prze-
suwany o cztery spacje.
Reguły stosowania wcięć jest trudniej opisać niż pokazać na przykładzie.
Najlepszą metodą osiągnięcia właściwego rozkładu kodu jest zapoznanie się
z kodem innego programisty, którego styl wydaje się najlepszy i łatwy do od-
czytania, i wzorowanie siÄ™ na nim. Ponadto liczne systemy edycyjne LISP-u
zawierają mechanizm tak zwanych "pretty-printers", który powoduje odpo-
wiednie przeformatowanie z zastosowaniem wcięć dowolnie napisanego ko-
du programu w LISP-ie.
Wskazówki dla programistów
Nie jest możliwe opisanie wszystkich aspektów techniki programowania
w LISP-ie w jednym rozdziale podręcznika. Opisane zostaną jednakże waż-
niejsze zagadnienia zwiÄ…zane z programowaniem w AutoLISP-ie. W razie
wystąpienia problemów w części kodu programu, często pomocne jest spraw-
dzenie, jak z podobnymi problemami poradzili sobie autorzy innych progra-
mów w AutoLISP-ie.
Obsługa błędów
AutoLISP udostępnia specjalny mechanizm postępowania z błędami użyt-
kownika lub programu. Funkcja *error* pozwala zagwarantować zwrócenie
określonych zmiennych systemowych lub wybranych stanów AutoCAD-a po
wystąpieniu nieoczekiwanego błędu. Dzięki tej definiowanej przez użytkow-
nika funkcji, można zapewnić sobie dostęp do warunku błędu i podać użyt-
kownikowi odpowiedni komunikat. Jeśli funkcja ta nie jest zdefiniowana lub
przypisane jest jej nil, standardowa procedura obsługi błędów zawiesza wy-
konanie programu AutoLISP-u po wystąpieniu błędu, wyświetla komunikat
błędu i zapis wywoływanych i wywołujących funkcji, do 100 poziomów
wgłąb. Często korzystniej jest pozostawić działającą standardową procedurę
obsługi błędów na czas uruchamiania programu.
Przed zdefiniowaniem własnej funkcji *error*, zalecane jest zwykle zachowa-
nie jej oryginalnej zawartości, tak by po zakończeniu działania programu
użytkowego można było przywrócić jej pierwotne znaczenie. Gdy zaistnieje
sytuacja błędu, AutoCAD wywołuje aktualnie zdefiniowaną funkcję *error*
podając jej argument, którym jest łańcuch tekstowy opisujący istotę błędu.
Zazwyczaj definiowana przez autora programu użytkowego funkcja *error*
powinna zapewniać niezauważalne wyjście z programu po wciśnięciu
Ctri+C lub wywołaniu funkcji exit. Typową metodą spełnienia tych warun-
ków jest umieszczenie w procedurze obsługi błędów następujących wyrażeń:
(if (/= msg "Function cancelled")
204 Właściwe techniki programowania
Rozdział 5
(if (= msg "quit / exit abort")
(princ)
(princ (strcat "\nBÅ‚Ä…d: " msg))
)
(princ)
)
Powyższy fragment kodu sprawdza przesłany do funkcji *error* komunikat
błędu i gwarantuje poinformowanie użytkownika o naturze błędu w przy-
padku, gdy faktycznie wystąpił rzeczywisty błąd, przynajmniej w odniesie-
niu do błędów znanych samemu AutoLISP-owi. Procedura nie zwraca nic, je-
śli w trakcie jej działania użytkownik anuluje ją wciskając Ctri+C. Nic nie
jest zwracane także wówczas, gdy warunki błędu zostały przewidziane
w programie i wołana jest funkcja exit. Zakładamy przy tym, że istota błędu
została wcześniej objaśniona z wykorzystaniem odpowiednich funkcji dru-
kujących (na przykład princ). W przypadku korzystania z funkcji princ na-
leży pamiętać, że jeśli procedura ma nie wyświetlać jako wartości zwracanej
ostatniego drukowanego komunikatu, na jej końcu musi znaleźć się dodat-
kowe wyrażenie kończące ją w sposób niezauważalny.
Jeśli wywołanie COFAJ jest wykorzystywane w celu umożliwienia jednokro-
kowego cofania skutków działania procedury, należy zapewnić równoważące
wywołanie COFAJ, uruchamiane w przypadku normalnego wyjścia z proce-
dury. W rzeczywistości może zachodzić potrzeba cofnięcia przez AutoCAD
wszystkich działań, albo jedynie ostatniej części czegokolwiek, co utworzyła
procedura. W celu określenia, jak (i czy w ogóle) ma być wywołane COFAJ,
programy mogą wykorzystywać zmienne systemowe UNDOCTL i UNDO-
MARKS.
Głównym zarzutem wobec stosowania procedur obsługi błędów jest fakt, że
są one takimi samymi funkcjami AutoLISP-uJak wszystkie inne i mogą być
anulowane przez użytkownika. Dlatego należy starać się tworzyć te funkcje
możliwie krótkie i szybkie w działaniu. Zwiększy to prawdopodobieństwo,
że w przypadku wywołania, wykonana zostanie cała procedura.
Sprawdzanie wprowadzanych danych
Należy zabezpieczać swój program przed niezamierzonymi błędami, spo-
wodowanymi przez użytkownika. Wiele potrafią w tym zakresie funkcje Au-
toLISP-u getxxx, gwarantujÄ…c zazwyczaj co najmniej syntaktycznÄ… popra-
wność informacji wprowadzonej przez użytkownika. Niebezpiecznie, a przy
tym łatwo jest jednak zapomnieć o sprawdzeniu zgodności z innymi kryte-
riami, narzucanymi przez program, a niemożliwymi do sprawdzenia przez
funkcje usługowe AutoLISP-u. Sprawdzanie poprawności wprowadzanych
danych jest żmudne, ale jego pominięcie może poważnie wpływać na kom-
pletność programu.
Wczytywanie
Programy w AutoLISP-ie są zwykle dostępne w postaci plików .Isp, przezna-
czonych do wczytania za pomocą funkcji load. Oprócz dostarczania funkcji,
dostępnych na żądanie użytkownika, funkcja load daje programiście możli-
wość poinformowania użytkownika, jak używać programu. AutoLISP war-
tościuje wszystkie wyrażenia wewnątrz pliku, dlatego zawarte w tym pliku
wywołania funkcji princ (oraz print, prin1 lub innych) umożliwiają wyświet-
lanie pożądanych informacji w linii zgłoszeń gotowości AutoCAD-a. Można
Właściwe techniki programowania 205
Zarządzanie pamięcią
także zapobiec wyświetlaniu przez AutoLISP ostatniej zwracanej wartości,
wpisując w ostatniej linii wyrażenie "(princ)".
Wczytywanie pliku daje jeszcze inną możliwość wywołania funkcji
AutoLISP-u. Wszystkie wyrażenia w pliku .Isp, nie będące częścią definicji
instrukcji defun, są wykonywane podczas wczytywania pliku. Własność tę
można wykorzystać do ustalenia wartości wybranych parametrów albo wy-
konać wszelkie inne potrzebne procedury wstępne, niezależnie od wyświet-
lenia informacji tekstowych, w sposób opisany poprzednio.
Obsługa języków narodowych
Jeśli program pisany w AutoLISP-ie ma być używany we współpracy z na-
rodowymi wersjami AutoCAD-a, standardowe polecenia i słowa kluczowe
AutoCAD-a będą automatycznie tłumaczone, jeśli zostaną poprzedzone zna-
kiem podkreślenia "_". Ilustruje to poniższy przykład:
(command "Jine" pt1 pt2 pt3 "_c")
Funkcje dostępu do elementów rysunkowych
Należy zdawać sobie sprawę, że funkcje dostępu do elementów są relatywnie
powolne. Zwykle bardziej opłacalne czasowo jest jednorazowe odczytanie za-
wartości określonego elementu rysunkowego (lub pozycji z tablicy symboli)
i przetrzymywanie jej w pamięci, niż wielokrotne pytanie AutoCAD-a o te
same dane. Należy tylko zapewnić poprawność przechowywanych danych:
jeśli użytkownik ma możliwość zmiany elementu lub pozycji tablicy symboli,
należy "ponownie wykorzystać funkcję dostępu do elementu rysunkowego
w celu sprawdzenia aktualności danych.
Transformacje punktów
Jeżeli w programie dokonywane są transformacje punktów za pomocą fun-
kcji trans, a konieczne jest przyspieszenie wykonywania odpowiedzialnej za
to części programu, można skonstruować własną macierz transformacji, wy-
korzystując funkcję trans tylko raz do transformacji każdego z "wektorów
bazowych": (0,0,0), (1,0,0), (0,1,0)1(0,0,1). Oczywiście pisanie w AutoLISP-ie
funkcji do mnożenia macierzy jest na tyle uciążliwe, że zwykle nie warto tego
robić, chyba że program wykonuje wiele transformacji.
Konwersje jednostek
Podczas pierwszego wywołania funkcji cvunit w celu wykonania konwersji
z lub na wybrane jednostki, musi ona odczytać z pliku acad.unt określający
je łańcuch alfanumeryczny. Jeśli program użytkowy ma do wykonania wiele
konwersji jednostek, bardziej efektywne jest dokonanie konwersji wartości
1.0 przez jednokrotne wywołanie funkcji cvunit, a następnie wykorzystywa-
nie zwróconej wartości jako współczynnika skali przy następnych konwer-
sjach. Jest to postępowanie skuteczne w odniesieniu do wszystkich jedno-
stek zdefiniowanych w pliku acad.unt, za wyjątkiem jednostek określają-
cych skale temperatury, które wymagają jednocześnie i współczynnika ska-
li, i przesunięcia.
206 Właściwe techniki programowania
Wyszukiwarka
Podobne podstrony:
Wykład 9 Zarządzanie pamięcią8 Systemy Operacyjne 21 12 2010 Zarządzanie Pamięcią Operacyjnąsołtys,systemy operacyjne, zarządzanie pamięciąZPT 05 Zarzadzanie ryzykiem odblokowany2006 08 Zarządzanie pamięcią w systemach operacyjnych [Inzynieria Oprogramowania]14 Zarządzanie pamięcią3 18 Zarządzanie pamięcią (2)9 Systemy Operacyjne 04 01 2011 Zarządzanie Pamięcią Operacyjną205 poznawcza pamiec1 09 10 st5więcej podobnych podstron