Lekcja programowania Najlepsze praktyki prapro

background image
background image

Idź do

• Spis treści
• Przykładowy rozdział
• Skorowidz

• Katalog online

• Dodaj do koszyka

• Zamów cennik

• Zamów informacje

o nowościach

• Fragmenty książek

online

Helion SA

ul. Kościuszki 1c

44-100 Gliwice

tel. 32 230 98 63

e-mail: helion@helion.pl

© Helion 1991–2011

Katalog książek

Twój koszyk

Cennik i informacje

Czytelnia

Kontakt

• Zamów drukowany

katalog

Lekcja programowania.
Najlepsze praktyki

Autorzy: Brian W. Kernighan, Rob Pike
Tłumaczenie: Łukasz Piwko
ISBN: 978-83-246-3226-8
Tytuł oryginału:

The Practice of Programming

Format: 172×245, stron: 272

Twórz zgodnie z trzema zasadami stanowiącymi kanon dobrego oprogramowania

• Prostota – czyli kod prosty i łatwy w obsłudze
• Ogólność – czyli kod działający dobrze w różnych sytuacjach i adaptujący się do nowych

warunków

• Przejrzystość – czyli kod łatwy do zrozumienia zarówno przez ludzi, jak i maszyny

Czy zdarzyło Ci się kiedykolwiek…

• pominąć oczywisty błąd w programie i spędzić cały dzień na szukaniu go?
• próbować wprowadzić sensowne zmiany w programie napisanym przez kogoś innego?
• przepisać program od nowa, bo nie dało się go zrozumieć?

Jeśli tak, w przyszłości na pewno chciałbyś tego uniknąć! Takie problemy dla zbyt wielu
programistów są niestety chlebem powszednim. Dzieje się tak między innymi dlatego, że
testowanie, diagnostyka, przenośność, wydajność czy styl programowania są często traktowane
po macoszemu przez osoby tworzące oprogramowanie. A świat rządzony przez olbrzymie
interfejsy, wciąż zmieniające się narzędzia, języki czy systemy nie sprzyja podstawowym zasadom
tworzenia dobrego kodu – prostocie, ogólności i przejrzystości.

Programowanie to coś więcej niż samo pisanie kodu. W książce „Praktyka programowania”
znajdziesz opis wszystkich zagadnień, z którymi styka się programista – od projektowania,
poprzez usuwanie usterek, testowanie kodu czy poprawę jego wydajności, po problemy związane
z poprawianiem oprogramowania napisanego przez innych. Wszystko zostało oparte na
zaczerpniętych z realnych projektów przykładach, napisanych w językach C, C++, Java i innych.

Tylko tutaj znajdziesz omówienia następujących zagadnień:

• Styl: pisanie kodu, który dobrze działa i przyjemnie się czyta
• Projektowanie: wybór algorytmów i struktur danych najlepiej nadających się

do określonego zadania

• Interfejsy: kontrolowanie relacji między składnikami programów
• Usuwanie błędów: szybkie i metodyczne wyszukiwanie błędów
• Testowanie: zapewnianie niezawodności i poprawności oprogramowania
• Wydajność: maksymalizowanie szybkości działania programów
• Przenośność: pisanie programów, które działają wszędzie bez żadnych zmian
• Notacja: wybór języków i narzędzi, które pozwalają maszynie zrobić więcej

Stwórz swój własny kod w najlepszym stylu!

background image

Spis treci

Wstp

7

1. Styl

11

1.1. Nazwy

13

1.2. Wyraenia i instrukcje

16

1.3. Spójno i idiomy

20

1.4. Makra w roli funkcji

28

1.5. Liczby magiczne

29

1.6. Komentarze

33

1.7. Dlaczego warto dba o styl?

38

2. Algorytmy i struktury danych

39

2.1. Przeszukiwanie

40

2.2. Sortowanie

42

2.3. Biblioteki

44

2.4. Sortowanie szybkie w Javie

47

2.5. Notacja O

50

2.6. Tablice rozszerzalne

51

2.7. Listy

54

2.8. Drzewa

59

2.9. Tablice mieszania

64

2.10. Podsumowanie

68

3. Projektowanie i implementacja

69

3.1. Algorytm acucha Markowa

70

3.2. Wybór struktury danych

72

3.3. Budowa struktury danych w jzyku C

73

3.4. Generowanie tekstu

77

3.5. Java

79

3.6. C++

83

3.7. Awk i Perl

86

3.8. Wydajno

88

3.9. Wnioski

89

background image

4

SPIS TRECI

4. Interfejsy

93

4.1. Wartoci oddzielane przecinkami

94

4.2. Prototyp biblioteki

95

4.3. Biblioteka dla innych

99

4.4. Implementacja w jzyku C++

108

4.5. Zasady projektowania interfejsów

112

4.6. Zarzdzanie zasobami

114

4.7. Obsuga bdów

117

4.8. Interfejsy uytkownika

121

5. Usuwanie bdów

125

5.1. Programy diagnostyczne

126

5.2. Dobre pomysy, atwe bdy

127

5.3. Brak pomysów, trudne bdy

131

5.4. Ostatnia deska ratunku

135

5.5. Bdy niepowtarzalne

138

5.6. Narzdzia diagnostyczne

140

5.7. Bdy popenione przez innych

143

5.8. Podsumowanie

144

6. Testowanie

147

6.1. Testuj kod podczas jego pisania

148

6.2. Systematyczne testowanie

153

6.3. Automatyzacja testów

157

6.4. Ramy testowe

159

6.5. Testowanie przecieniowe

163

6.6. Porady dotyczce testowania

166

6.7. Kto zajmuje si testowaniem

167

6.8. Testowanie programu markov

168

6.9. Podsumowanie

170

7. Wydajno

171

7.1. Wskie gardo

172

7.2. Mierzenie czasu wykonywania i profilowanie programu

177

7.3. Strategie przyspieszania

181

7.4. Regulowanie kodu

184

7.5. Oszczdzanie pamici

188

7.6. Szacowanie

191

7.7. Podsumowanie

193

8. Przenono

195

8.1. Jzyk

196

8.2. Nagówki i biblioteki

202

8.3. Organizacja programu

204

8.4. Izolacja

208

8.5. Wymiana danych

209

8.6. Kolejno bajtów

210

8.7. Przenono a uaktualnianie

213

8.8. Internacjonalizacja

215

8.9. Podsumowanie

218

background image

SPIS TRECI

5

9. Notacja

221

9.1. Formatowanie danych

222

9.2. Wyraenia regularne

228

9.3. Programowalne narzdzia

234

9.4. Interpretery, kompilatory i maszyny wirtualne

237

9.5. Programy, które pisz programy

242

9.6. Generowanie kodu za pomoc makr

246

9.7. Kompilacja w locie

247

A Epilog

253

B Zebrane zasady

255

Skorowidz

259

background image

5

Usuwanie bdów

bug

b. Usterka lub bd w maszynie, planie itp. poch. USA. 11 marca 1889 Pall Mall Gaz. 1/1: Powiadomiono
mnie, e pan Edison nie pi ju od dwóch dni, próbujc znale usterk (ang.
bug) w swoim fonografie
— wyraenie oznaczajce poszukiwanie rozwizania problemu i sugerujce, e gdzie wewntrz ukry
si wyimaginowany insekt, który powoduje trudnoci.

Oxford English Dictionary, wyd. 2.

W poprzednich czterech rozdziaach przedstawilimy sporo przykadów kodu i za kadym razem
udawalimy, e wszystkie one od razu prawidowo dziaay. Oczywicie tak nie byo — w ka-
dym z nich pocztkowo a roio si od bdów. Sowo bug mimo i nie powstao w rodowisku
programistycznym, jest niewtpliwie jednym z najczciej uywanych sów w tej dziedzinie.
Dlaczego tworzenie oprogramowania jest takie trudne?

Jednym z powodów jest to, e na zoono programów ma wpyw liczba interakcji wyst-

pujcych midzy ich skadnikami, a programy s pene skadników i relacji. Istnieje wiele
technik sucych do zmniejszania liczby powiza midzy komponentami. Zalicza si do nich
ukrywanie informacji, abstrakcj i interfejsy oraz waciwoci jzyka, które su do ich reali-
zowania. S równie techniki zapewniajce integralno projektów programów — dowodzenie
poprawnoci programów, modelowanie, analiza wymaga, formalna weryfikacja — ale adna
z nich nie zmienia sposobu, w jaki tworzy si oprogramowanie. Wszystkie okazay si sku-
teczne tylko w rozwizywaniu bardzo maych problemów. Rzeczywisto jest taka, e zawsze
znajd si bdy, które bdziemy wykrywa za pomoc testowania i eliminowa za pomoc
technik usuwania bdów (ang. debugging).

Dobry programista wie, e usuwanie bdów zajmuje tyle samo czasu, co pisanie kodu,

i dlatego zawsze stara si wyciga z nich wnioski. Kady wykryty bd jest nauk na przyszo,
jak unikn powtórki takiej sytuacji lub jak rozpozna, e miaa ona miejsce.

Usuwanie bdów to trudna i nieprzewidywalnie czasochonna sztuka, dlatego naley zro-

bi wszystko, aby mie z ni jak najmniej do czynienia. Sposobów na skrócenie czasu usuwania
usterek jest wiele, np. staranne opracowywanie projektu, pisanie w dobrym stylu, sprawdzanie

background image

126

5. USUWANIE BDÓW

warunków brzegowych, stosowanie asercji i testów sensownoci, programowanie defensywne,
projektowanie dobrych interfejsów, ograniczanie iloci danych globalnych oraz korzystanie
z narzdzi diagnostycznych. Profilaktyka zawsze jest lepsza od leczenia.

Jaka jest rola jzyka? Najwiksz si od zawsze ksztatujc ewolucj jzyków programo-

wania jest ch zapobiegania wystpowaniu bdów poprzez odpowiednie dobranie waciwoci
jzyka. Niektóre cechy jzyków programowania pozwalaj wyeliminowa cae grupy bdów, np.
sprawdzanie zakresu w operacjach indeksowania, ograniczenie lub wrcz wyczenie moliwoci
stosowania wskaników, automatyczne odzyskiwanie pamici, acuchowe typy danych, kon-
trola typów wejcia-wyjcia i rygorystyczna kontrola typów. Z drugiej strony pewne wasnoci
jzyków zwikszaj prawdopodobiestwo powstawania bdów: instrukcje goto, zmienne globalne,
nieograniczony dostp do wskaników i automatyczne konwersje typów. Programici powinni
wiedzie, które waciwoci jzyka s potencjalnie ryzykowne, i zachowa szczególn ostro-
no przy ich uywaniu. Ponadto powinni wczy wszystkie narzdzia diagnostyczne kom-
pilatora i zwraca uwag na zgaszane przez niego ostrzeenia.

Waciwoci jzykowe, które uniemoliwiaj powstawanie pewnych bdów, maj swoj cen.

Jeli jzyk programowania wysokiego poziomu automatycznie usuwa niektóre bdy, cen jest
to, e atwiej jest nam popenia bdy wyszego poziomu. aden jzyk nie sprawi, e cakiem
przestaniemy popenia bdy.

Chocia wolelibymy, aby byo inaczej, kady programista najwicej czasu spdza na testo-

waniu kodu i usuwaniu bdów. W tym rozdziale omówimy techniki produktywnego i szyb-
kiego usuwania bdów. Do testowania wrócimy jeszcze w rozdziale 6.

5.1. Programy diagnostyczne

Kompilatory najwaniejszych jzyków programowania s wyposaone w zaawansowane pro-
gramy diagnostyczne (ang. debugger). Narzdzia takie wchodz w skad wielu zintegrowanych
rodowisk programistycznych oferujcych w jednym pakiecie narzdzia do pisania i edytowa-
nia kodu, kompilacji oraz wykonywania utworzonych programów. Programy diagnostyczne
maj graficzne interfejsy, za pomoc których mona wykonywa kod programu po jednej in-
strukcji lub funkcji albo zatrzymywa wykonywanie po wykonaniu okrelonych wierszy lub
spenieniu zdefiniowanych warunków. Ponadto oferuj moliwo formatowania i wywietla-
nia biecych wartoci zmiennych.

Program diagnostyczny mona uruchomi bezporednio, jeli wiadomo, e wystpi bd.

Niektóre takie programy automatycznie przejmuj sterowanie, gdy wykryj, i co si nie po-
wiodo w czasie wykonywania programu. Zwykle wykrycie miejsca wystpienia bdu jest nie-
trudne. W tym celu naley tylko sprawdzi sekwencj funkcji, które byy w tym czasie wykonywane
(stos wywoa) oraz wywietli wartoci zmiennych lokalnych i globalnych. Tyle informacji
czsto wystarcza do znalezienia róda problemu. Jeli to zawiedzie, mona skorzysta z punk-
tów wstrzymania i funkcji wykonywania programu krok po kroku, aby znale miejsce, w którym
po raz pierwszy wystpiy jakie anomalie.

W rkach dowiadczonego programisty korzystajcego z dobrego rodowiska program dia-

gnostyczny moe by bardzo efektywnym i wydajnym narzdziem, które pozwala zaoszczdzi
mnóstwo nerwów. Skoro dostpne s tak wspaniae narzdzia, po co kto miaby usuwa bdy,
nie korzystajc z ich pomocy? Po co usuwaniu bdów powica a cay rozdzia?

Istnieje ku temu kilka dobrych powodów, zarówno obiektywnych, jak i wynikajcych z na-

szego osobistego dowiadczenia. Dla niektórych jzyków spoza gównego nurtu nie ma adne-
go programu diagnostycznego albo, jeeli jest, jego funkcjonalno jest bardzo ograniczona.

background image

5.2. DOBRE POMYSY, ATWE BDY

127

Ponadto dziaanie narzdzi diagnostycznych zaley od systemu operacyjnego, a wic nie zaw-
sze moesz mie dostp do swoich ulubionych programów tego rodzaju. Programy diagno-
styczne sabo radz sobie z niektórymi rodzajami programów, np. wieloprocesowymi i wielowt-
kowymi, systemami operacyjnymi i systemami rozproszonymi. W takich przypadkach konieczne
jest uycie technik niszego poziomu. Programista jest wówczas zdany na siebie, do dyspozycji
ma tylko instrukcje drukujce oraz wasne dowiadczenie i umiejtno analizowania kodu.

Osobicie staramy si nie naduywa programów diagnostycznych i ograniczamy si do

sprawdzenia za ich pomoc stosu wywoa oraz wartoci paru zmiennych. Jednym z powodów
podjcia takiej decyzji jest to, e mona bardzo atwo pogubi si w skomplikowanej pltaninie
struktur danych i cieek wykonawczych. Naszym zdaniem wykonywanie kodu krok po kroku
jest mniej produktywne ni jego dokadniejsze przeanalizowanie oraz dodanie kilku instrukcji
wyjciowych i samosprawdzajcego si kodu w krytycznych miejscach. Na przejrzenie danych
zwróconych przez kilka roztropnie rozmieszczonych instrukcji drukujcych potrzeba mniej
czasu ni na wykonywanie kolejnych instrukcji za pomoc klikni mysz. Podjcie decyzji,
gdzie wstawi instrukcj drukowania, zajmuje mniej czasu ni przechodzenie do krytycznego
fragmentu kodu po jednej instrukcji, nawet jeli dokadnie wiadomo, które to miejsce. Co
waniejsze, instrukcje diagnostyczne pozostaj w programie, a sesje programu diagnostycznego
znikaj.

Szukanie bdów po omacku za pomoc programu diagnostycznego rzadko bywa produk-

tywne. O wiele lepiej jest uy go do sprawdzenia stanu programu w chwili wystpienia usterki
i na podstawie zdobytych informacji zastanowi si, jak mogo do tej sytuacji doj. Programy
diagnostyczne bywaj niezwykle skomplikowane i trudne do opanowania. Zwaszcza poczt-
kujcy programista moe mie z nich sto pociech i tysic utrapie. Jeli programowi diagno-
stycznemu zada si niewaciwe pytanie, to zwykle zwróci on odpowied, ale nie wiadomo, czy
poprawn.

Mimo to program diagnostyczny moe by niezwykle pomocny i kady programista powinien

mie go pod rk. W wielu przypadkach jest to pierwsze narzdzie, z którego pomocy si ko-
rzysta. Jeli jednak nie masz programu diagnostycznego albo napotkasz wyjtkowo trudny do
rozwizania problem, dziki technikom opisanym w tym rozdziale i tak szybko wyjdziesz z opresji.
Ponadto nauczysz si dziki nim efektywniej korzysta z programów diagnostycznych, gdy
dotycz tego, jak analizowa bdy i szuka ich prawdopodobnych przyczyn.

5.2. Dobre pomysy, atwe bdy

Oho! Co jest nie tak. Mój program pad, wydrukowa bzdury albo nie chce przesta dziaa.
Co robi?

Pocztkujcy programici w takich sytuacjach najczciej zrzucaj win na kompilator, bi-

bliotek i wszystko, tylko nie ich kod. Dowiadczeni programici te by tak chcieli, ale bdc
realistami, doskonale wiedz, e wikszo bdów powstaje wycznie z ich winy.

Na szczcie gównie robimy proste bdy, które mona wyeliminowa prostymi technikami.

Przeanalizuj zwrócone przez program bdne dane i spróbuj wywnioskowa, w jaki sposób mogy
powsta. Przejrzyj dane diagnostyczne wyprodukowane przed wystpieniem awarii. Jeli masz
tak moliwo, sprawd stos wywoa. Po wykonaniu tych czynnoci bdziesz ju mie jakie
pojcie na temat tego, co i gdzie si stao. Przemyl to. Jak mogo do tego doj? Przeanalizuj
zachowanie programu od pocztku i zastanów si, co mogo spowodowa jego wadliwe dziaanie.

Diagnostyka bdów wymaga analizowania w mylach przeszoci, podobnie jak wykrywa-

nie sprawców morderstw. Zdarzyo si co niemoliwego, a jedyna informacja, jak posiadamy,

background image

128

5. USUWANIE BDÓW

to fakt, e rzeczywicie miao to miejsce. Aby odkry przyczyn problemów, musimy si cofn
w czasie. Po znalezieniu penego wyjanienia bdziemy wiedzie, jak naprawi program, a przy
okazji prawdopodobnie odkryjemy jeszcze kilka innych rzeczy, których si nie spodziewalimy.

Szukaj znajomych wzorców. Odpowiedz sobie na pytanie, czy ju co takiego widziae. Od-
powied typu „Gdzie ju to widziaem” zwykle stanowi pierwszy krok do zrozumienia, a nie-
jednokrotnie oznacza nawet rozwizanie. Czsto wystpujce bdy maj pewne cechy szcze-
gólne. Przykadowo pocztkujcy programici czsto pisz tak:

? int n;
? scanf("%d", n);

zamiast tak:

int n;
scanf("%d", &n);

co zwykle koczy si prób odczytu danych z miejsca poza wyznaczonym obszarem pami-

ci przy pobieraniu wiersza danych wejciowych. Wykadowcy jzyka C natychmiast rozpoznaj
ten problem.

Niewyczerpanym ródem prostych bdów s le dobrane typy danych i ich konwersje

w funkcjach printf i scanf:

? int n = 1;
? double d = PI;
? printf("%d %f\n", d, n);

Znakiem szczególnym tego rodzaju bdu jest czasami pojawienie si niedorzecznych war-

toci: wielkich liczb cakowitych albo niewiarygodnie maych lub duych wartoci zmienno-
przecinkowych. Powyszy program uruchomiony na komputerze SPARC firmy Sun zwróci
nastpujc astronomiczn liczb (z koniecznoci podzielon na kilka wierszy):

1074340347 268156158598852001534108794260233396350\
1936585971793218047714963795307788611480564140\
0796821289594743537151163524101175474084764156\
422771408323839623430144.000000

Kolejny pospolity bd dotyczy wczytywania liczb typu double za pomoc funkcji scanf

przy uyciu cigu %f zamiast %lf. Niektóre kompilatory wyapuj takie bdy, poniewa
sprawdzaj zgodno typów argumentów funkcji scanf i printf z acuchami formatu. Przy
wczonych wszystkich ostrzeeniach kompilator gcc w systemie GNU dla powyszego wywo-
ania funkcji printf zwróci nastpujce informacje:

x.c:9: warning: int format, double arg (arg 2)
x.c:9: warning: double format, different type arg (arg 3)

Kolejny rodzaj bdu, który atwo rozpozna po znakach szczególnych, to brak inicjalizacji

zmiennej lokalnej. Wynikiem tego zaniedbania jest zwykle niesychanie dua warto, bdca
pozostaoci po tym, co uprzednio znajdowao si w tym miejscu w pamici. Niektóre kompi-
latory mog przestrzega przed takimi bdami, aczkolwiek do tego konieczne moe by w-

background image

5.2. DOBRE POMYSY, ATWE BDY

129

czenie opcji sprawdzania podczas kompilacji, a poza tym — aden kompilator nie wychwyci
wszystkiego. Take pami alokowana za pomoc takich funkcji, jak malloc, realloc i new,
moe by bezuyteczna, jeli nie zostanie zainicjalizowana.

Przeanalizuj ostatni zmian. Jakie zmiany w programie zostay ostatnio wprowadzone? Jeli
rozwijajc program, za kadym razem dodajesz do niego tylko jedn rzecz, to s wycznie dwie
moliwoci: nowy kod spowodowa wystpienie bdu albo ujawni bd w starym kodzie.
W znalezieniu problemu pomocne jest dokadne przejrzenie ostatnich zmian. Jeli bd wyst-
puje w nowej wersji programu, a nie ma go w starszej, to nowy kod jest czci problemu. Dla-
tego trzeba zawsze zachowywa przynajmniej poprzedni wersj programu, aby w razie kopo-
tów móc porówna zachowanie z najnowsz wersj. Ponadto naley prowadzi rejestr
wprowadzanych zmian i naprawianych bdów, by nie musie zdobywa tych informacji na
nowo, gdy trzeba bdzie naprawi kolejny bd. Pomocne s w tym systemy kontroli kodu ró-
dowego i inne techniki ledzenia historii zmian.

Nie popeniaj dwukrotnie tego samego bdu. Gdy naprawisz jaki bd, zastanów si, czy nie
móg on wystpi jeszcze gdzie indziej. Taka sytuacja przydarzya si jednemu z nas krótko
przed rozpoczciem pisania tego rozdziau. Miao to miejsce w prostym, pisanym dla kolegi
prototypie przedstawiajcym schemat obsugi opcjonalnych argumentów:

? for (i = 1; i < argc; i++) {
? if (argv[i][0] != '-')

/* Koniec opcji */

? break;
? switch (argv[i][1]) {
? case 'o':

/* Nazwa pliku wyjciowego */

? outname = argv[i];
? break;
? case 'f':
? from = atoi(argv[i]);
? break;
? case 't':
? to = atoi(argv[i]);
? break;
? ...

Niedugo po wypróbowaniu programu kolega poinformowa nas, e do nazwy pliku zawsze

doczany by przedrostek -o. Byo nam wstyd, ale bd okaza si atwy do naprawienia. Po-
prawilimy jedn instrukcj:

outname = &argv[i][2];

Po naprawieniu tego bdu i odesaniu programu do uytkownika niebawem przysza ko-

lejna wiadomo. Tym razem program niepoprawnie obsugiwa argumenty typu -f123: po
konwersji warto liczbowa zawsze wynosia zero. To ten sam bd, co wczeniej. Poprawilimy
zatem nastpn klauzul case:

from = atoi(&argv[i][2]);

Poniewa autor si spieszy, nie zauway, e ten sam bd wystpowa jeszcze w dwóch in-

nych miejscach, przez co zanim udao si ostatecznie oczyci program z kilku wystpie iden-
tycznego bdu, potrzebna bya jeszcze jedna wymiana dowiadcze z naszym koleg.

background image

130

5. USUWANIE BDÓW

W atwym kodzie nietrudno popeni bd, poniewa widzc znany problem, przestajemy

by ostroni. Nawet jeli kod jest tak prosty, e mógby go napisa z zamknitymi oczami, lepiej
nie zamykaj oczu podczas jego pisania.

Nie odkadaj poprawiania bdów na póniej. Popiech przy wykonywaniu pracy moe mie
szkodliwe skutki take w innych sytuacjach. Nigdy nie ignoruj awarii. Zawsze od razu popraw
bd, bo moe si nie powtórzy, a bdzie za póno. Synny sta si przykad takiego niedopa-
trzenia w misji sondy „Pathfinder” wysanej na Marsa. Po jej pomylnym ldowaniu na po-
wierzchni planety w lipcu 1997 roku komputery pokadowe resetoway si mniej wicej raz na
dzie, co stanowio wielk zagadk dla inynierów. Gdy znaleli przyczyn problemów, zdali
sobie spraw, e mieli ju z tym do czynienia. Takie zachowania komputerów zdarzay si ju
w fazie wstpnych testów, ale zostay zlekcewaone, poniewa inynierowie pracowali wówczas
nad czym innym. Zostali wic zmuszeni do zajcia si tym dopiero póniej, gdy maszyna
znajdowaa si miliony kilometrów od nich i znacznie trudniej byo j naprawi.

Sprawdzaj stos wywoa. Mimo i programy diagnostyczne pozwalaj bada programy pod-
czas dziaania, to najczciej s wykorzystywane do analizowania stanu programu, który prze-
sta dziaa. Do najbardziej przydatnych informacji dostarczanych przez program diagnostycz-
ny naley numer wiersza kodu ródowego, w którym wystpi problem. Cenn wskazówk s
równie nieprawdopodobne wartoci argumentów (puste wskaniki, bardzo due wartoci ca-
kowite, podczas gdy spodziewane s mae, ujemne wartoci tam, gdzie powinny by dodatnie,
acuchy znaków nienalecych do alfabetu).

Oto typowy przykad z opisu algorytmów sortowania przedstawionego w rozdziale 2. Aby

posortowa tablic liczb cakowitych, naley wywoa funkcj qsort, przekazujc jej jako ar-
gument funkcj icmp porównujc liczby cakowite:

int arr[N];
qsort(arr, N, sizeof(arr[0]), icmp);

Zaómy, e pomykowo podano nazw scmp funkcji porównujcej acuchy:

? int arr[N];
? qsort(arr, N, sizeof(arr[0]), scmp);

Jako e kompilator w tym przypadku nie moe wykry niezgodnoci typów, nieuchronnie

napytalimy sobie biedy. Program ulega awarii spowodowanej prób dostpu do niedozwolo-
nego miejsca w pamici. Program diagnostyczny dbx zwraca nastpujce informacje o stosie
wywoa (przeredagowane, aby zmieciy si na stronie):

0 strcmp(0xla2, 0xlc2) ["strcmp.s":31]
1 scmp(p1 = 0x10001048, p2 = 0x1000105c) ["badqs.c":13]
2 qst(0x10001048, 0x10001074, Ox400b20, 0x4) ["qsort.c":147]
3 qsort(0x10001048, 0xlc2, 0x4, 0x400b20) ["qsort.c":63]
4 main() ["badqs.c":45]
5 __istart() ["crt1tinit.s":13]

Z tych danych wynika, e awaria nastpia w funkcji strcmp. Wida, e przekazywane do

niej dwa wskaniki s o wiele za mae, co niewtpliwie jest oznak kopotów. W stosie wywoa
zostay podane orientacyjne numery wierszy, w których nastpio wywoanie kadej funkcji.
Wiersz nr 13 w naszym pliku badqs.c zawiera takie wywoanie:

background image

5.3. BRAK POMYSÓW, TRUDNE BDY

131

return strcmp(v1, v2);

wskazujce na ródo bdu.
Przy uyciu programu diagnostycznego mona równie wywietli wartoci zmiennych lo-

kalnych i globalnych, które take mog naprowadzi nas na jaki trop.
Najpierw przeczytaj, a potem poprawiaj. Jedn z najbardziej niedocenianych efektywnych
technik wykrywania bdów jest uwane przeczytanie kodu i zastanowienie si nad nim bez do-
konywania jakichkolwiek zmian. Pokusa, aby chwyci za klawiatur i zacz wprowadza zmiany,
jest bardzo dua, ale naley si jej oprze. Istnieje due ryzyko, e w ten sposób nie dowiesz si,
co tak naprawd szwankuje, i zmienisz nie to, co trzeba, pogarszajc jeszcze tylko sytuacj. Za-
pisanie najwaniejszej czci programu na papierze pozwala spojrze na niego z nieco innej
perspektywy, ni ogldajc go na ekranie, i zachca do refleksji. Nie stosuj jednak tej techniki
rutynowo. Drukowanie kodu programu to marnotrawstwo drzew, a poza tym i tak trudno
ogarn ca struktur kodu, jeli zajmuje on kilka stron. Co wicej, po wprowadzeniu pierw-
szej zmiany cay wydruk nadaje si do wyrzucenia.

Zrób sobie krótk przerw. Czasami w kodzie widzisz to, co chciaby widzie, a nie to, co

jest w nim rzeczywicie zapisane. Jeli na chwil si oderwiesz, to po powrocie moe zaczniesz
wicej uwagi zwraca na prawdziwe znaczenie kodu.

Oprzyj si pokusie poprawiania kodu natychmiast. Warto chwil si przed tym zastanowi.

Objanij swój kod komu innemu. Dobrym sposobem jest objanienie napisanego przez siebie
kodu innej osobie. Zdarza si, e w ten sposób sami odkrywamy sedno problemu. Czasami wy-
starczy tylko powiedzie kilka zda, aby stwierdzi ze wstydem: „Niewane, ju wiem, co jest
nie tak. Przepraszam, e Ci przeszkadzam”. To niezwykle skuteczna metoda. W rol suchacza
moe si wcieli nawet osoba niebdca programist. W pewnym uniwersyteckim orodku
komputerowym przy stanowisku pracy pomocy technicznej umieszczono pluszowego misia.
Studenci chccy uzyska pomoc najpierw musieli swój problem objani misiowi i dopiero po-
tem mogli porozmawia z czowiekiem.

5.3. Brak pomysów, trudne bdy

„Nie mam zielonego pojcia, o co moe chodzi”. Jeli kompletnie nie wiesz, w czym moe
tkwi problem, to zaczynaj si schody.

Wymu powtarzalno bdu. Pierwsz czynnoci, któr naley wykona, jest sprawienie,
aby bd pojawia si na danie. Tropienie bdu pojawiajcego si tylko raz na jaki czas nie
jest przyjemne. Powi chwil na sporzdzenie danych wejciowych i opracowanie takich pa-
rametrów, które pozwol Ci niezawodnie spowodowa wystpienie bdu za kadym razem.
Nastpnie zapakuj to wszystko w jeden pakiet, aby móc go przywoywa jednym przyciskiem
albo kilkoma klawiszami. Jeli bd jest trudny do wytropienia, czynnoci te trzeba bdzie po-
wtórzy wielokrotnie, a wic lepiej je sobie maksymalnie uproci.

Jeli bdu nie da si odtworzy za kadym razem, spróbuj zrozumie dlaczego. Czy czsto-

tliwo jego wystpowania zaley od jakich specyficznych warunków? Nawet jeeli nie moesz
wymusi pojawienia si bdu za kadym razem, warto spróbowa przynajmniej skróci czas
oczekiwania na jego wystpienie.

Jeli program moe dostarcza danych diagnostycznych, skorzystaj z tej moliwoci. Pro-

gramy symulacyjne, takie jak program generujcy acuchy Markowa z rozdziau 3., powinny
zawiera opcj generowania danych diagnostycznych, np. w celu sprawdzenia wartoci pocztkowej

background image

132

5. USUWANIE BDÓW

generatora liczb losowych, dziki którym mona spróbowa odtworzy uzyskane wyniki. Wiele
programów zawiera takie opcje i warto je uwzgldni take w swoich programach.

Dziel i rzd. Czy dane wejciowe wywoujce awari programu mona jako zmniejszy albo
bardziej skoncentrowa? Stwórz minimalny zestaw danych wejciowych, które powoduj wy-
stpowanie bdu, aby zredukowa liczb moliwoci. Jakie zmiany powoduj, e bd przestaje
si pokazywa? Spróbuj wyodrbni takie przypadki testowe, które precyzyjnie koncentruj si
na szukanym bdzie. Kady taki przypadek powinien by zaplanowany na uzyskanie okrelone-
go wyniku, potwierdzajcego lub wykluczajcego pewn hipotez na temat róda problemów.

Uyj algorytmu przeszukiwania binarnego. Odrzu poow danych wejciowych i sprawd,

czy program nadal zwraca niepoprawny wynik. Jeli nie, wró do poprzedniego stanu i odrzu
drug poow danych wejciowych, a pierwsz tym razem pozostaw. T sam metod mona
zastosowa w odniesieniu do tekstu programu. Usu jak cz kodu ródowego, która Twoim
zdaniem nie powinna mie zwizku z wystpujcym bdem, i sprawd, co si stanie. Przy ma-
nipulowaniu duymi przypadkami testowymi i duymi ilociami kodu ródowego programu
bardzo pomocny jest edytor kodu z opcj cofania zmian, która zapewnia, e nie utracimy bdu.

Przeprowad numeryczn analiz usterek. Czasami na trop bdu mona wpa, analizujc
pewne liczbowe cechy usterki. Po napisaniu jednego z podrozdziaów tej ksiki spostrzegli-
my, e niektóre litery gdzie si z niego ulotniy. To byo bardzo dziwne. Poniewa tekst zo-
sta skopiowany i wklejony do pliku z innego miejsca, doszlimy do wniosku, e problem tkwi
w funkcji kopiowania lub wklejania edytora tekstu. Ale od czego rozpocz poszukiwanie b-
du? Postanowilimy dokadniej przyjrze si danym i odkrylimy, e braki znaków wystpuj
w równych odstpach w tekcie. Obliczylimy, e odlego midzy dwoma kolejnymi brakami
zawsze wynosia 1 023 bajty. Taka regularno jest bardzo podejrzana. Poszukalimy w kodzie
ródowym edytora wartoci zblionych do 1 024 i znalelimy kilka rzeczy wartych uwagi.
Jedna z nich znajdowaa si w wieo napisanym kodzie, a wic postanowilimy zacz od niej.
Szybko spostrzeglimy bd. Bya to klasyczna pomyka o jeden, która powodowaa, e zerowy
bajt kasowa ostatni znak w buforze o rozmiarze 1 024 bajtów.

Na trop bdu wpadlimy dziki przeanalizowaniu liczbowych waciwoci zwizanych z uster-

k. Ile czasu nam to zajo? Kilka minut spdzilimy w osupieniu, pi minut zajo nam od-
krycie prawidowoci w znikaniu znaków i kolejnych piciu minut potrzebowalimy na znale-
zienie i usunicie bdu. Rozwizanie tego problemu przy uyciu programu diagnostycznego
byoby bardzo trudne, gdy w gr wchodziy dwa wieloprocesowe programy obsugiwane za
pomoc myszy i komunikujce si ze sob poprzez system plików.

Wywietlaj dodatkowe informacje, aby zorientowa si, jak dziaa program. Jeli nie rozu-
miesz, co robi kod, to najatwiejszym i najmniej kosztownym wydajnociowo sposobem na do-
wiedzenie si tego jest dodanie instrukcji wywietlajcych róne informacje. W ten sposób
mona upewni si co do susznoci swoich ocen lub zweryfikowa hipotezy na temat tego, co
dziaa le. Jeli np. wydaje Ci si, e niemoliwe jest dotarcie do pewnej czci kodu, dodaj in-
strukcj wywietlajc informacj: „Nie mona tu wej”. Jeeli póniej komunikat ten zosta-
nie pokazany, przesu wywietlajc go instrukcj nieco wyej, aby dowiedzie si, w którym
miejscu zaczynaj si kopoty. Analogicznie moesz te wywietla informacj: „Udao si tu
wej” i przesuwa j stopniowo coraz dalej, by znale ostatnie miejsce, w którym nic zego si
nie dzieje. Komunikaty powinny róni si od siebie, aby za kadym razem byo wiadomo,
który zosta wywietlony.

Komunikaty powinny by zwize i zawsze mie jednakowy format, aby daway si atwo

przeanalizowa programicie lub programom pomocniczym, takim jak np. narzdzie grep su-
ce do porównywania wzorców. Programy podobne do grep s nieocenionym wsparciem przy

background image

5.3. BRAK POMYSÓW, TRUDNE BDY

133

przeszukiwaniu tekstu — prost implementacj takiego narzdzia przedstawiamy w rozdziale 9.
Jeli wywietlasz wartoci zmiennych, to za kadym razem formatuj komunikat w taki sam
sposób. W jzykach C i C++ wskaniki prezentuj w postaci liczb szesnastkowych przy uyciu
specyfikatorów formatu %x lub %p. Dziki temu dowiesz si, czy dwa wskaniki maj t sam
warto bd s ze sob w jaki sposób powizane. Naucz si odczytywa wartoci wskaników
oraz rozpoznawa prawdopodobne i nieprawdopodobne wartoci, np. zero, liczby ujemne, nie-
typowe wartoci i mae liczby. Take znajomo formatów adresów przydaje si podczas uy-
wania programu diagnostycznego.

Jeli jest moliwo, e program zwróci bardzo du ilo danych, to moe dane te wystar-

czy wydrukowa w postaci pojedynczych liter, np. A, B itd., aby zwile pokaza, dokd pro-
gram doszed.

Pisz samosprawdzajcy si kod. Jeli potrzebujesz wicej informacji, to moesz napisa wa-
sn funkcj sprawdzajc okrelony warunek, wywietlajc wartoci odpowiednich zmiennych
i zamykajc program:

/* check: sprawdza warunek, drukuje i koczy dziaanie */
void check(char *s)
{
if (var1 > var2) {
printf("%s: var1 %d var2 %d\n", s, var1, var2);
fflush(stdout);

/* Zapewnia wysanie wszystkich danych na wyjcie */

abort();

/* Sygnalizuje nienormalne zakoczenie dziaania programu */

}
}

Funkcja check wywouje standardow funkcj jzyka C o nazwie abort, która przedwcze-

nie koczy dziaanie programu w celu umoliwienia jego analizy w programie diagnostycznym.
Oczywicie funkcj check mona te zmieni w taki sposób, aby po wydrukowaniu informacji
nie zamykaa programu.

Nastpnie wywoaj funkcj check wszdzie tam, gdzie tego potrzebujesz:

check("Przed podejrzanym kodem");
/* … Podejrzany kod … */
check("Za podejrzanym kodem");

Po naprawieniu bdu nie usuwaj funkcji check z kodu ródowego. Umie j w komenta-

rzu albo wycz j za pomoc opcji programu diagnostycznego, aby móc jej uy ponownie, gdy
wystpi kolejny trudny do rozwizania problem.

Jeli pojawi si takie problemy, zakres obowizków funkcji mona rozszerzy np. o weryfikacj

i wywietlanie struktur danych. Mona nawet zastosowa bardziej ogólne podejcie i napisa
procedur na bieco sprawdzajc spójno struktur danych i innych informacji. W programach,
w których wykorzystywane s skomplikowane struktury danych, warto takie funkcje napisa,
zanim jeszcze pojawi si problemy, i uczyni je integraln czci programu. Wówczas w razie
kopotów mona je bez przeszkód wczy. Nie ograniczaj si do korzystania z nich tylko pod-
czas usuwania bdów. Moesz ich uywa we wszystkich fazach rozwoju programu, a jeli nie
pochaniaj zbyt duo zasobów, to nawet warto je pozostawi wczone cay czas. W duych
programach, takich jak systemy komutacyjne w komunikacji, czsto znaczn cz kodu stanowi
podprogramy monitorujce przepywajce informacje i sprzt i zgaszajce wszelkie usterki,
niekiedy nawet automatycznie je naprawiajc.

background image

134

5. USUWANIE BDÓW

Utwórz dziennik. Kolejnym sposobem jest utworzenie pliku dziennika, w którym bd zapi-
sywane dane diagnostyczne w cile okrelonym formacie. W razie wystpienia awarii w pliku
takim powinien znale si zapis tego, co dziao si tu przed tym wydarzeniem. Serwery sie-
ciowe i inne programy dziaajce w sieci utrzymuj dzienniki, w których zapisuj ogromne iloci
informacji o ruchu sieciowym — na ich podstawie kontroluj siebie i swoich klientów. Poniej
przedstawiamy fragment takiego pliku pochodzcego z lokalnego systemu (tekst dopasowany
do strony):

[Sun Dec 27 16:19:24 1998]
HTTPd: access to /usr/local/httpd/cgi-bin/test.html
failed for m1.cs.bell-labs.com,
reason: client denied by server (CGI non-executable)
from http://m2.cs.bell-labs.com/cgi-bin/test.pl

Aby w pliku dziennika pojawiy si rekordy danych, trzeba pamita o zapisaniu w nim

zawartoci buforów wejcia i wyjcia. Funkcje wyjciowe, takie jak printf, zwykle buforuj
swoje wyniki, aby zoptymalizowa dziaanie operacji drukowania. Przy nienormalnym zako-
czeniu pracy programu informacje te mog zosta utracone. W jzyku C zapisanie wszystkich
tego typu danych przed zamkniciem programu mona wymusi za pomoc funkcji fflush. Jej
odpowiednikiem w jzykach C++ i Java jest funkcja flush zapisujca dane ze strumieni wyj-
ciowych. Jeeli nie przeszkadzaj Ci dodatkowe koszty wydajnociowe, problem moesz roz-
wiza raz na zawsze, wyczajc buforowanie operacji zapisu danych w dzienniku. Su do
tego standardowe funkcje o nazwach setbuf i setvbuf. Wywoanie funkcji setbuf(fp, NULL)
spowoduje wyczenie buforowania w strumieniu fp. Standardowe strumienie bdów (stderr,
cerr

i System.err) maj domylnie wyczone buforowanie.

Rysuj obrazy. Czasami w testowaniu i usuwaniu bdów doskona pomoc s obrazy. Oczywi-
cie najbardziej pomagaj w zrozumieniu struktur danych, o czym przekonalimy si w roz-
dziale 2., i w pisaniu programów graficznych, ale to nie jedyne ich zastosowania. Na wykresie
punktowym lepiej wida rozkad wartoci ni w kolumnach liczb. Na histogramie mona a-
twiej wychwyci anomalie w ocenach z egzaminów, losowych liczbach, rozmiarach kubeków
alokowanych przez specjalne funkcje i uywanych w tablicach mieszania itd.

Jeli nie rozumiesz, co dzieje si w Twoim programie, spróbuj sobie pomóc, opatrujc

struktury danych danymi statystycznymi, które dodatkowo przedstaw w postaci wykresu. Po-
niej zaprezentowano wykresy sporzdzone dla programu Markowa z rozdziau 3. w wersji na-
pisanej w jzyku C. Na o x zostay naniesione dugoci acuchów mieszania, a na o y — licz-
by elementów w tych acuchach. Jako danych wejciowych uylimy naszego standardowego
tekstu z Ksigi Psalmów (42 685 sów, 22 482 przedrostki). Pierwsze dwa wykresy zostay spo-
rzdzone dla dobrych mnoników 31 i 37, a trzeci — dla koszmarnej wartoci 128. W dwóch
pierwszych przypadkach dugo adnego acucha nie przekracza 15 lub 16 elementów, a wik-
szo acuchów skada si z 5 i 6 elementów. W trzecim przypadku dane s bardziej rozpro-
szone, najduszy acuch ma 187 elementów i wystpuje bardzo duo acuchów zawieraj-
cych po 20 i wicej elementów.

background image

5.4. OSTATNIA DESKA RATUNKU

135

Korzystaj z narzdzi. Dobrze uyj narzdzi oferowanych przez swoje rodowisko pracy. Na
przykad program porównujcy pliki, taki jak diff, zestawia wyniki programu, którego wyko-
nywanie zakoczyo si powodzeniem, i takiego, którego wykonywanie zakoczyo si niepo-
wodzeniem, dziki czemu mona przeanalizowa rónice. Jeli program diagnostyczny zwraca
due iloci danych, to przeszukuj je za pomoc takiego programu jak grep oraz analizuj przy
uyciu edytora. Wstrzymaj si od drukowania na papierze danych diagnostycznych: kompute-
ry lepiej radz sobie z analiz duych iloci danych ni ludzie. Uyj skryptów powoki, aby
zautomatyzowa proces przetwarzania danych diagnostycznych.

Pisz proste programy do weryfikacji hipotez i swojego zrozumienia sposobu dziaania kodu.

Czy mona np. zwolni pusty wskanik?

int main (void)
{
free(NULL);
return 0;
}

Programy do kontroli kodu ródowego, takie jak RCS, umoliwiaj rejestracj kolejnych

wersji programu, dziki czemu mona sprawdzi, jakie zmiany zostay wprowadzone, i w razie
potrzeby przywróci jedn ze starszych wersji. Oprócz funkcji podgldu najnowszych zmian
programy te oferuj równie moliwo znalezienia najczciej modyfikowanych fragmentów
kodu. W tych miejscach czsto kryj si rozmaite bdy.

Pisz dokumentacj. Jeli poszukiwania róda problemów bd si przeciga, po pewnym
czasie zapomnisz, co ju zostao sprawdzone, a czego jeszcze nie wiesz. Jeeli zaczniesz zapisy-
wa wykonane testy i ich wyniki, to bdziesz mie pewno, e niczego nie przeoczysz. Notujc
informacje o problemie, lepiej zapamitasz, e kiedy ju co podobnego widziae, a przy oka-
zji bdziesz mie pomoc, gdy zechcesz objani problem komu innemu.

5.4. Ostatnia deska ratunku

Co robi, jeli adna z wymienionych technik nie pomaga? Teraz moe nadesza pora na wy-
konanie programu krok po kroku w programie diagnostycznym. Jeli masz kompletnie bdne
wyobraenie o tym, jak co dziaa, przez co szukasz problemu w niewaciwym miejscu albo
szukasz tam, gdzie trzeba, lecz go nie widzisz, program diagnostyczny moe zmusi Ci do

background image

136

5. USUWANIE BDÓW

spojrzenia na sprawy z innej perspektywy. Bdy niedajce si wykry z powodu niewaciwego
rozumienia istoty problemu s najgorsze. W takich przypadkach mechaniczna pomoc jest bez-
cenna.

Czasami bdne przekonanie dotyczy bardzo prostych zagadnie, s to np.: niepoprawna

kolejno wykonywania operatorów, uycie niewaciwego operatora, wcicia kodu niezgodne
z jego struktur czy bdy zakresu dostpnoci zmiennych polegajce na tym, e zmienna lo-
kalna zasania zmienn globaln albo zmienna globalna wcina si w zakres lokalny. Programi-
ci czsto zapominaj przykadowo o tym, e operatory & i | stoj dalej w kolejce do wykonania
ni operatory == i !=. Dlatego zdarza im si pisa taki kod:

? if (x & 1 == 0)
? ...

i nie mog zrozumie, dlaczego ten warunek nigdy nie jest speniony. Czasami polizgnie

si palec i omykowo zamiast jednego znaku równoci napisz si dwa albo odwrotnie:

? while ((c == getchar()) != EOF)
? if (c = '\n')
? break;

Albo podczas pracy nad programem nie zostanie usunity niepotrzebny kod:

? for (i = 0; i < n; i++);
? a[i++] = 0;

Niektóre problemy wynikaj z popiechu:

? switch (c) {
? case '<':
? mode = LESS;
? break;
? case '>':
? mode = GREATER;
? break;
? defualt:
? mode = EQUAL;
? break;
? }

Czasami wpisanie argumentów w niepoprawnej kolejnoci powoduje bd, którego nie mona

wykry przez mechanizm sprawdzania typów, np.:

? memset(p, n, 0);

/* Zapisuje n zer w p */

zamiast

memset(p, 0, n);

/* Zapisuje n zer w p */

Czasami co zostaje zmienione bez wiedzy programisty, np. nie wiemy, e jaka procedura

moe zmienia pewne globalne lub wspóuytkowane zmienne.

background image

5.4. OSTATNIA DESKA RATUNKU

137

Nieraz uyty algorytm lub struktura danych zawieraj fatalny bd, którego po prostu nie

dostrzegamy. Przygotowujc materiay do omówienia list powizanych, sporzdzilimy pakiet
funkcji sucych do tworzenia nowych elementów listy oraz doczania ich na pocztku i ko-
cu struktury danych itp. (funkcje te mona obejrze w rozdziale 2.). Oczywicie sprawdzilimy,
czy wszystko jest w porzdku za pomoc specjalnie napisanego w tym celu programu testowego.
Kilka pierwszych testów zostao zakoczonych pomylnie, ale w pewnym momencie nastpia
efektowna awaria. Oto kod ródowy tamtego programu:

? while (scanf("%s %d", name, &value) != EOF) {
? p = newitem(name, value);
? list1 = addfront(list1, p);
7 list2 = addend(list2, p);
? }
? for (p = list1; p != NULL; p = p->next)
? printf("%s %d\n", p->name, p->value);

A trudno uwierzy, ile kopotów sprawio nam dostrzeenie, e pierwsza ptla umieszczaa

ten sam wze p w obu listach, przez co gdy przystpowalimy do drukowania, wskaniki byy
beznadziejnie pomieszane.

Takie bdy s trudne do wykrycia, poniewa podwiadomie widzimy to, co chcielibymy

widzie. Dlatego w takich przypadkach pomocny jest program diagnostyczny, który zmusza
nas do zastanowienia si nad innymi moliwociami i przeledzenia rzeczywistego dziaania
programu zamiast mylenia o tym, co on powinien robi. Czasami problem wynika z bdu
w ogólnej strukturze programu. Aby wykry co takiego, trzeba ponownie przejrze swoje wstp-
ne zaoenia.

Zauwamy przy okazji, e w przykadzie dotyczcym list bd znajdowa si w kodzie te-

stujcym, co znacznie utrudniao jego znalezienie. To straszne, jak atwo mona zmarnowa
czas na poszukiwaniu bdów, których nie ma, bo problem tkwi w programie testujcym, albo
na testowaniu niewaciwej wersji programu tudzie poniewa zaniedbao si aktualizacj bd
kompilacj programu przed wznowieniem testowania.

Jeli mimo znacznego wysiku nie uda Ci si znale bdu, to zrób sobie przerw. Odpocznij

i chwilowo zajmij si czym innym. Porozmawiaj z koleg i popro go o pomoc. Rozwizanie
moe pojawi si nagle, nie wiadomo skd, a nawet jeli nie, po powrocie do pracy nie bdziesz
ju tkwi w tym samym zauku.

Zdarza si te, cho niezwykle rzadko, e ródem problemów jest kompilator, biblioteka,

system operacyjny, a nawet sprzt. Mona to podejrzewa zwaszcza wówczas, gdy bd wyst-
pi bezporednio po wprowadzeniu zmian w rodowisku. Nigdy nie naley rozpoczyna szuka-
nia bdów od tych miejsc, ale po wykluczeniu wszystkich innych moliwoci to moe by
ostatnie, co nam zostanie. Kiedy przenosilimy duy program do formatowania tekstu z sys-
temu Unix do komputera PC. Kompilacja zakoczya si bez adnych problemów, ale program
dziaa bardzo dziwnie: opuszcza mniej wicej co drugi znak w danych wejciowych. Pierwsz
nasz myl byo to, e ma to jaki zwizek z uywaniem 16-bitowych liczb cakowitych za-
miast 32-bitowych albo z kolejnoci bajtów. Jednak po wydrukowaniu znaków, tak jak byy przed-
stawiane ptli gównej, odkrylimy, e bd tkwi w standardowym pliku nagówka ctype.h
dostarczanym przez producenta kompilatora. Zawiera on implementacj funkcji isprint
w postaci makra funkcyjnego:

? #define isprint(c) ((c) >= 040 && (c) < 0177)

a gówna ptla pobierania danych bya zdefiniowana nastpujco:

background image

138

5. USUWANIE BDÓW

? while (isprint(c = getchar()))
? ...

Za kadym razem, gdy na wejciu pojawiaa si spacja (o wartoci ósemkowej 40, któr sto-

suje si w zym stylu zamiast zapisu ' ') lub znak o wyszym numerze, funkcja getchar bya
wywoywana po raz drugi, poniewa makro ewaluowao swój argument dwa razy, przy czym
pierwszy znak znika bezpowrotnie. Nasz kod ródowy moe nie by szczytem elegancji —
warunek ptli mógby by prostszy — ale plik nagówkowy od dostawcy kompilatora bez naj-
mniejszych wtpliwoci zawiera bd.

Przykady tego bdu mona spotka do dzi. Ponisze makro pochodzi z wci uywanych

plików nagówkowych innego producenta:

? #define __iscsym(c) (isalnum(c) || ((c) == '_'))

Obfitym ródem bdów powodujcych nienormalne dziaanie programów s wycieki pamici,

tzn. przypadki nieodzyskania nieuywanych ju fragmentów pamici. Kolejnym jest niezamy-
kanie plików, które prowadzi do zapenienia tablicy plików otwartych, przez co nie mona
otwiera nastpnych. Awarie programów zawierajcych wycieki pamici czsto wygldaj bar-
dzo tajemniczo. Poniewa do usterki dochodzi po wyczerpaniu pewnych zasobów, nie da si
odtworzy specyficznych zdarze.

Z rzadka kopoty sprawia sprzt. W procesorze Pentium z 1994 roku wystpowa bd, któ-

ry powodowa, e niektóre obliczenia na liczbach zmiennoprzecinkowych daway ze wyniki.
Ta szeroko nagoniona usterka w projekcie urzdzenia duo firm kosztowaa, ale gdy ju j
zidentyfikowano, bd dao si powtarza. Jeden z najdziwniejszych bdów, jakie widzielimy
w swojej karierze, znajdowa si w starym programie kalkulatora dziaajcym w systemie dwu-
procesorowym. Czasami dla wyraenia 0/5 zwraca warto 0.5, a niekiedy drukowa jak in-
n warto, typu 0.7432, cho trzeba przyzna, e jak ju to robi, to konsekwentnie. Nie dao
si w aden sposób przewidzie, czy w danym przypadku wynik bdzie poprawny, czy nie.
W kocu odkryto, i ródem problemu jest usterka w jednostce odpowiedzialnej za obliczenia
zmiennoprzecinkowe w jednym z procesorów. Poniewa do wykonywania kalkulatora by lo-
sowo wybierany albo jeden, albo drugi procesor, raz wyniki byy poprawne, a innym razem
niedorzeczne.

Wiele lat temu uywalimy maszyny, której wewntrzn temperatur mona byo oszacowa na

podstawie liczby niepoprawnych bitów niskich w obliczeniach zmiennoprzecinkowych. Oblu-
zowaa si jedna z kart ukadu elektronicznego i w miar jak rosa temperatura, karta ta od-
chylaa si coraz bardziej, co powodowao, e wicej bitów zostawao odcitych od pyty mon-
taowej.

5.5. Bdy niepowtarzalne

Najtrudniejsze do wytropienia s te bdy, które pojawiaj si nieregularnie — najczciej
przyczyn ich powstawania nie jest banalne uszkodzenie sprztu. Jednak cenn wskazówk jest
ju sam fakt, e tak si zachowuj. Mona dedukowa, e prawdopodobn przyczyn bdu jest
nie usterka w algorytmie, lecz raczej to, i program korzysta z danych, które za kadym razem
s inne.

Sprawd, czy wszystkie zmienne s zainicjalizowane. Moliwe, e która z nich otrzymuje

losow warto odpowiadajc temu, co byo ostatnio zapisane w przypisywanym jej obszarze

background image

5.5. BDY NIEPOWTARZALNE

139

pamici. W jzykach C i C++ najczstszymi sprawcami s zmienne lokalne funkcji i pami
uzyskiwana za pomoc funkcji alokujcych. Wszystkim zmiennym przypisz konkretne warto-
ci. Jeli w programie uywana jest warto pocztkowa generatora liczb losowych, której cz-
sto nadaje si warto na podstawie aktualnej daty, to przypisz jej jak sta warto, np. 0.

Jeeli dodanie kodu diagnostycznego powoduje zmian zachowania lub wrcz zniknicie

bdu, to mona podejrzewa nieprawidowo przy alokacji pamici — jaka instrukcja zapi-
suje dane poza przydzielonym obszarem i dodanie kodu diagnostycznego wprowadza modyfi-
kacj rozmieszczenia elementów w pamici, której skutkiem jest zmiana efektu wywoywanego
przez bd. Wikszo funkcji wyjciowych, od printf po funkcje okien dialogowych, alokuje
pami samodzielnie, co dodatkowo zaciemnia obraz.

Jeli miejsce awarii wydaje si odlege od wszystkiego, co mogoby by zepsute, to najbar-

dziej prawdopodobn przyczyn problemu jest bdne zmienienie zawartoci obszaru pamici
w miejscu, które jest uywane dopiero póniej. Czasami problem dotyczy tzw. wiszcego
wskanika, czyli omykowego zwrócenia przez funkcj wskanika na zmienn lokaln i pó-
niejszego jego uycia. rodkiem profilaktycznym przed tak odroczon katastrof jest zwróce-
nie adresu zmiennej lokalnej:

? char *msg(int n, char *s)
? {
? char buf[100];
?
? sprintf (buf, "Bd %d: %s\n", n, s);
? return buf;
? }

Zanim wskanik zwrócony przez funkcj msg zostanie uyty, bdzie ju wskazywa nic nie-

znaczce miejsce w pamici. Musisz przydzieli pami za pomoc funkcji malloc, uy sta-
tycznej tablicy albo zada, aby wywoujcy dostarczy pami.

Uycie dynamicznie alokowanej wartoci ju po jej zwolnieniu objawia si w podobny spo-

sób. Wspominalimy o tym w rozdziale 2., przy okazji omawiania funkcji freeall. Poniszy
kod zawiera bd:

? for (p = listp; p != NULL; p = p->next)
? free (p);

Pamici, która zostaa zwolniona, nie wolno uywa, poniewa jej zawarto moga si

zmieni i nie ma pewnoci, e instrukcja p->next wci wskazuje waciwe miejsce w pamici.

W niektórych implementacjach funkcji malloc i free dwukrotne zwolnienie elementu po-

woduje uszkodzenie wewntrznych struktur danych, ale nie wywouje to adnych kopotów
przez duszy czas, dopóki kolejne wywoanie nie wywróci si na tym baaganie. Pewne funkcje
alokacyjne maj opcje diagnostyczne, za pomoc których mona sprawdzi spójno pola dzia-
a przed kadym wywoaniem. Wcz je, jeli próbujesz wytropi nieregularnie zachowujcy
si bd. Jeeli w ten sposób nic nie wskórasz, moesz napisa wasn funkcj alokujc, która
mogaby sprawdza niespójno swoich wasnych zachowa albo zapisywa w dzienniku
wszystkie wywoania, aby mona je byo póniej przeanalizowa. Napisanie funkcji alokujcej
pami, gdy nie zaley nam bardzo na szybkoci dziaania, jest atwe, a wic strategi t mona
wykona, jeeli problem jest powany. Istniej te wietne komercyjne narzdzia suce do
sprawdzania zarzdzania pamici oraz wykrywajce bdy i wycieki pamici. Jeli nie masz do
nich dostpu, moesz wykorzysta niektóre z ich zalet, piszc wasne funkcje malloc i free.

background image

140

5. USUWANIE BDÓW

Jeeli jedna osoba nie ma problemów z programem, a inna ma, to znaczy, e istnieje jaka

usterka, która ujawnia si tylko w okrelonych warunkach. Odpowiedzialne za to mog by
jakie pliki wczytane przez program, prawa dostpu do plików, zmienne rodowiskowe, cieki
dostpu polece, ustawienia domylne lub pliki uywane podczas uruchamiania programu. Trudno
cokolwiek w takich sytuacjach doradzi, poniewa aby odtworzy rodowisko, w którym program
zawodzi, trzeba by t drug osob.

wiczenie 5.1. Napisz wasne wersje funkcji malloc i free, których bdzie mona uy do
rozwizywania problemów z zarzdzaniem pamici. Jednym z rozwiza moe by sprawdza-
nie w kadym wywoaniu caej przestrzeni roboczej. Odmiennym podejciem jest zapisywanie
danych diagnostycznych w dzienniku, aby mogy zosta przetworzone przez inny program.
Bez wzgldu na to, któr metod wybierzesz, na pocztku i kocu kadego alokowanego bloku
dodaj znaczniki, by ujawni ewentualne przypadki przekroczenia zakresu z obu stron.

5.6. Narzdzia diagnostyczne

W znajdowaniu bdów pomocne s nie tylko programy diagnostyczne. Istnieje wiele innych
narzdzi, które mog nam pomóc dotrze do wanych informacji w wielkich zbiorach danych,
znale anomalie lub tak zmieni ukad danych, aby atwiej mona byo zobaczy, co si dzieje.
Wiele z nich znajduje si w standardowym wyposaeniu warsztatu. Niektóre zostay napisane
w celu znalezienia konkretnego bdu lub przeanalizowania specyficznego problemu.

W tym podrozdziale omówimy prosty program o nazwie strings, który jest szczególnie

pomocny w przegldaniu plików skadajcych si gównie ze znaków niedrukowalnych, a wic
np. plików wykonywalnych i tajemniczych formatów binarnych uywanych przez niektóre
edytory tekstu. We wntrzu czsto kryj si róne cenne informacje, takie jak tekst dokumen-
tu, komunikaty o bdach i nieudokumentowanych opcjach, nazwy plików i katalogów, a take
nazwy funkcji, które mogy by wywoane przez program.

Programu strings uywamy równie do znajdowania tekstu w innych plikach binarnych.

Wiele plików graficznych zawiera znaki ASCII opisujce program, w którym zostay utworzone,
a pliki skompresowane i archiwa (np. ZIP) mog zawiera nazwy plików. Wszystkie te infor-
macje mona odkry za pomoc programu strings.

W systemach uniksowych istnieje ju implementacja programu strings, chocia nieco inna

od tej, któr przedstawimy tutaj. Rozpoznaje ona programy na wejciu i bada tylko tekst i seg-
menty danych, ignorujc tablic symboli. Za pomoc opcji -a mona j zmusi do zbadania
caego pliku.

Program strings pobiera tekst ASCII z plików binarnych, tak e mona go póniej wczy-

ta lub przetworzy przez inne programy. Jeli znaleziony komunikat o bdzie nie ma adnego
identyfikatora, to moe by trudno odgadn, jaki program go zgosi, nie mówic ju, dlacze-
go to zrobi. Wówczas moe pomóc przeszukanie podejrzanych katalogów przy uyciu polece-
nia zblionego do zapisanego niej:

% strings *.exe *.dll | grep 'Tajemniczy komunikat'

Funkcja strings wczytuje plik i drukuje wszystkie acuchy skadajce si przynajmniej

z MINLEN = 6 drukowalnych znaków.

background image

5.6. NARZDZIA DIAGNOSTYCZNE

141

/* strings: pobiera znaki drukowalne ze strumienia */
void strings(char *name, FILE *fin)
{
int c, i;
char buf[BUFSIZ];

do {

/* Jeden raz dla kadego acucha */

for (i = 0; (c = getc(fin)) != EOF; ) {
if (!isprint(c))
break;
buf[i++] = c;
if (i >= BUFSIZ)
break;
}
if (i >= MINLEN)

/* Drukuje, jeli acuch jest wystarczajco dugi */

printf("%s:%.*s\n", name, i, buf);
} while (c != EOF);
}

acuch formatu %.*s uyty w wywoaniu funkcji printf pobiera dugo acucha z na-

stpnego argumentu (i), poniewa acuch (buf) nie jest zakoczony zerem.

Ptla do-while znajduje i drukuje kady acuch, a dziaanie koczy, gdy napotka znak

koca pliku. Dziki temu, e na kocu funkcji znajduje si sprawdzenie koca pliku, funkcja
getc

oraz ptle acuchowe mog mie wspólny warunek zakoczenia i jedno wywoanie funkcji

printf

moe obsugiwa koniec acucha, koniec pliku oraz zbyt dugie acuchy.

W standardowej ptli zewntrznej ze sprawdzeniem warunku na pocztku lub pojedynczej

ptli z funkcj getc i bardziej skomplikowanym kodem ródowym konieczne by byo dwu-
krotne wywoanie funkcji printf. Takie rozwizanie zastosowalimy na pocztku, ale zrobilimy
bd w instrukcji wywoujcej funkcj printf. Poprawilimy go w jednym miejscu, lecz zapo-
mnielimy o jeszcze dwóch innych („Czy popeniem ten sam bd jeszcze gdzie indziej?”).
Wówczas stao si jasne, e program trzeba napisa ponownie, aby byo w nim mniej powtó-
rze kodu. Tak doszlimy do ptli do-while.

Funkcja main programu strings wywouje funkcj strings dla kadego pliku przekazanego

jej jako argument:

/* main: znajduje znaki drukowalne w plikach */
int main(int argc, char *argv[])
{
int i;
FILE *fin;

setprogname("strings");
if (argc == 1)
eprintf("Sposób uycia: nazwy plików");
else {
for (i = 1; i < argc; i++) {
if ((fin = fopen(argv[i], "rb")) == NULL)
weprintf("Nie mona otworzy pliku %s:", argv[i]);
else {
strings(argv[i], fin);
fclose(fin);
}
}

background image

142

5. USUWANIE BDÓW

}
return 0;
}

Moe si dziwisz, e funkcja strings nie pobiera danych ze swojego standardowego stru-

mienia wejciowego, gdy nie zostan podane adne pliki. Pocztkowo to robia. Aby wyjani,
dlaczego teraz tego nie robi, musimy opowiedzie histori pewnego bdu.

Oczywistym testem, za pomoc którego mona sprawdzi program strings, jest urucho-

mienie go na nim samym. Program dziaa prawidowo w systemie Unix, ale w systemie Win-
dows 95 polecenie

C:\> strings <strings.exe

zwrócio dokadnie pi wierszy danych:

!This program cannot be run in DOS mode
'.rdata
@.data
.idata
.reloc

Pierwszy wiersz wyglda jak komunikat o bdzie, przez co zmarnowalimy troch czasu na

dowiedzenie si, e jest to acuch zapisany w programie, a dane wyjciowe s poprawne, przy-
najmniej jak na razie. Czasami zdarza si, i sesja diagnostyczna zostaje przerwana z powodu
niezrozumienia róda pochodzenia komunikatu.

Ale danych wyjciowych powinno by wicej, wic gdzie si podziay? Wreszcie której no-

cy owiecio mnie („Gdzie ju to widziaem!”). Jest to problem z przenonoci, o którym sze-
rzej piszemy w rozdziale 8. Pierwsza wersja programu wczytywaa dane tylko ze standardowego
wejcia i uywaa do tego celu funkcji getchar. Ale w systemie Windows funkcja ta zwraca
znak koca pliku, jeli w danych tekstowych napotka konkretny bajt (0x1A, czyli znak Ctrl+Z).
To powodowao przedwczesne koczenie pracy programu.

Jest to cakowicie poprawne zachowanie, ale nie tego oczekiwalimy, biorc pod uwag na-

sze dowiadczenia z uywania programu w systemie Unix. Rozwizaniem jest otwarcie pliku
w trybie binarnym przy uyciu trybu „rb”. Ale strumie stdin jest ju otwarty i nie da si
zmieni jego trybu w aden standardowy sposób (mona by byo uy funkcji takich jak fdopen
i setmode, ale nie nale one do standardu jzyka C).W efekcie stajemy przed wyborem jednej
z kilku nieprzyjemnych moliwoci: zmusi uytkownika do podania nazwy pliku, dziki czemu
program bdzie dobrze dziaa w systemie Windows, cho jest to nietypowe rozwizanie dla
systemu Unix; po cichu tworzy niepoprawne odpowiedzi, gdy uytkownik systemu Windows
usiuje wczyta dane ze standardowego wejcia; albo zastosowa kompilacj warunkow, by
dostosowa zachowanie programu do rónych systemów, co zmniejsza jego przenono. Zde-
cydowalimy si na pierwsz z wymienionych moliwoci, poniewa dziki temu program
wszdzie bdzie dziaa tak samo.

wiczenie 5.2. Program strings drukuje acuchy zawierajce przynajmniej MINLEN znaków,
co czasami powoduje zwrócenie wikszej iloci danych, ni potrzeba. Zmodyfikuj program
strings

tak, aby przyjmowa opcjonalny argument sucy do okrelania minimalnej dugoci

acucha.

background image

5.7. BDY POPENIONE PRZEZ INNYCH

143

wiczenie 5.3. Napisz funkcj vis kopiujc dane wejciowe na wyjcie i zamieniajc bajty
niedrukowalne, takie jak znak Backspace, znaki sterujce i znaki nienalece do zestawu ASCII
na symbole w formacie \Xhh, przy czym hh oznacza szesnastkow reprezentacj danego znaku.
W przeciwiestwie do strings funkcja vis jest najbardziej przydatna przy analizowaniu da-
nych zawierajcych niewielk liczb znaków niedrukowalnych.

wiczenie 5.4. Jaki wynik zwróci funkcja vis, jeli na wejciu otrzyma acuch \X0A? Co
mona zrobi, aby funkcja vis zwracaa niedwuznaczne wyniki?

wiczenie 5.5. Rozszerz zakres dziaania funkcji, tak aby przetwarzaa sekwencje plików, amaa
dugie wiersze w dowolnym miejscu i usuwaa wszystkie niedrukowalne znaki. Jakie jeszcze inne
zadania zgodne z przeznaczeniem programu mogaby spenia ta funkcja?

5.7. Bdy popenione przez innych

Niewielu programistów ma przyjemno tworzy nowy system od podstaw. Znacznie czciej
uywaj, modyfikuj, a wic i poprawiaj, kod napisany przez innych programistów.

Wszystko, co napisalimy do tej pory na temat znajdowania i eliminowania bdów, ma za-

stosowanie take do bdów popenionych przez kogo innego. Przed przystpieniem do pracy
konieczne jest jednak zbadanie organizacji programu oraz zrozumienie sposobu mylenia i pracy
poprzednika. W pewnym bardzo duym projekcie programistycznym uyto okrelenia „odkry-
cie”, stanowicego cakiem dobr przenoni. Zadanie polega na odkryciu, o co chodzi w ko-
dzie, którego my nie napisalimy.

W takich przypadkach bardzo pomocne s róne narzdzia. Uywajc programów do prze-

szukiwania tekstu, takich jak grep, mona znale wszystkie wystpienia wybranej nazwy. Ge-
neratory odsyaczy:g (ang. cross-referencer) pozwalaj zapozna si ze struktur programu. Wy-
kres przedstawiajcy wywoania funkcji jest pomocny, jeli nie jest zbyt duy. Wykonywanie
kodu po jednej instrukcji za pomoc programu diagnostycznego pozwala odkry kolejno zda-
rze. Zagldajc do historii wersji programu, mona dowiedzie si, jak program rozwija si w
czasie. Czste zmiany oznaczaj, e kod jest sabo zrozumiany albo podlega zmieniajcym si
wymaganiom, a wic moe stanowi potencjalne ródo bdów.

Czasami musisz szuka bdów w oprogramowaniu, za które nie odpowiadasz i którego kod

ródowy nie jest dostpny. W takich przypadkach musisz zidentyfikowa i scharakteryzowa
bd na tyle dobrze, aby móc go precyzyjnie omówi w raporcie i przy okazji opracowa jakie
dobre „obejcie” pozwalajce go wyeliminowa.

Kiedy wyda Ci si, e znalaze bd w nie swoim programie, przede wszystkim upewnij si,

i to na pewno jest bd, aby nie marnowa czasu autora i nie narazi si na utrat reputacji.

Gdy znajdziesz bd w kompilatorze, równie upewnij si, e to rzeczywicie bd kompila-

tora, a nie Twojego programu. Przykadowo w jzykach Ci C++ nie okrelono, czy operacja
bitowego przesunicia w prawo powinna wstawia bity zerowe (przesunicie logiczne), czy po-
wiela bit znaku (przesunicie arytmetyczne). Z tego powodu niektórzy pocztkujcy progra-
mici myl, e konstrukcje typu

? i = -1;
? printf ("%d\n", i >> 1);

background image

144

5. USUWANIE BDÓW

s bdne, jeli nie zwróc oczekiwanego wyniku. Jest to jednak kwestia przenonoci, gdy

powyszy kod moe rónie si zachowywa w rozmaitych systemach i nie bdzie to oznaczao
bdu. Sprawd swój test w rónych systemach i upewnij si, e dobrze rozumiesz, co si dzieje.
Najlepiej skontroluj te definicj jzyka.

Sprawd, czy bd nie jest znany. Czy masz najnowsz wersj programu? Czy istnieje lista

poprawionych bdów? Wikszo programów jest wydawana w wielu rónych wersjach. Jeli
znajdziesz usterk w wersji 4.0b1, to wcale nie musi jej by w wersji 4.04b2 albo moe w jej
miejsce powsta nowa. W kadym razie niewielu programistów pasjonuje si poprawianiem
bdów w starszych wersjach programów.

Wreszcie postaw si w roli osoby, która otrzyma Twój raport. Na pewno chcesz dostarczy

wacicielowi programu jak najlepszy przypadek testowy. Nie bdziesz zbyt pomocny, jeli
bd uda Ci si ujawni tylko przy duych ilociach danych wejciowych, w wyszukanym ro-
dowisku albo przy zastosowaniu wielu plików pomocniczych. Postaraj si ograniczy test do
jak najmniejszego samodzielnego pakietu. Docz wszystkie mogce si przyda informacje,
takie jak wersja programu, rodzaj uytego kompilatora, system operacyjny czy opis sprztu.
Dla bdnej wersji funkcji isprint z podrozdziau 5.4 moglibymy dostarczy poniszy pro-
gram testowy:

/* Program testowy ujawniajcy bd w funkcji isprint */
int main(void)
{
int c;
while (isprint(c = getchar()) || c != EOF)
printf ("%c", c);
return 0;
}

Jako przypadek testowy moe posuy dowolny wiersz tekstu zawierajcy drukowalne znaki,

poniewa na wyjciu pojawi si tylko poowa danych wejciowych:

% echo 1234567890 | isprint_test
24680
%

Najlepsze powiadomienia o bdach to takie, które do zademonstrowania bdu wymagaj

uycia jednego lub najwyej dwóch wierszy danych wejciowych w wieym systemie i zawie-
raj rozwizanie. Wysyaj takie powiadomienia o bdach, jakie sam chciaby otrzymywa.

5.8. Podsumowanie

Przy odrobinie dobrych chci usuwanie bdów moe by dobr rozrywk, jak rozwizywanie
amigówek. Jednak bez wzgldu na to, czy nam si to podoba, czy nie, sztuk t bdziemy
uprawia czsto i regularnie. Poniewa fajnie by byo, gdyby bdy nie istniay, staramy si pi-
sa jak najlepszy kod od samego pocztku. W dobrze napisanym kodzie nie tylko jest mniej
bdów, lecz take atwiej je znale, jeli ju si pojawi.

Po zauwaeniu bdu w programie naley najpierw zastanowi si, co mona wywniosko-

wa z jego cech szczególnych. Skd móg si wzi? Czy wyglda znajomo? Czy zmienio si
co w programie? Czy w danych, które spowodoway jego wystpienie, jest co szczególnego?
Czasami wystarczy kilka dobrze dobranych przypadków testowych i kilka instrukcji drukujcych.

background image

LEKTURA UZUPENIAJCA

145

Jeli nie ma adnych tropów, to i tak najlepiej jest zacz od dokadnego przemylenia

sprawy i próby zawenia liczby podejrzanych miejsc. Jedn z moliwoci jest stopniowe ogra-
niczanie zbioru danych wejciowych, aby uzyska niewielki zestaw powodujcy awari. Inn
moliwoci jest usuwanie po kolei fragmentów kodu ródowego, które nie powinny mie
z tym nic wspólnego. Mona do programu doda kod sprawdzajcy, który wcza si dopiero
po wykonaniu przez program okrelonej liczby dziaa. Wszystkie wymienione techniki to
elementy ogólnej strategii „dziel i rzd”, która równie dobrze sprawdza si zarówno w diagno-
zowaniu programów, jak i w polityce i dziaaniach wojennych.

Korzystaj take z innych pomocy. Niezwykle przydatne bywa objanienie dziaania

kodu komu innemu (choby pluszowemu misiowi). Posu si programem diagnostycznym
do sprawdzenia zawartoci stosu wywoa. Uyj którego z komercyjnych narzdzi do wykry-
wania wycieków pamici, przypadków naruszenia granic tablic, podejrzanego kodu itp. Z moliwo-
ci wykonywania kodu po jednej instrukcji skorzystaj wówczas, gdy stanie si jasne, e le ro-
zumiesz, jak dziaa kod.

Poznaj siebie i rodzaje bdów, które popeniasz. Kiedy znajdziesz i usuniesz jaki bd,

sprawd, czy w innych miejscach programu nie ma jeszcze podobnych usterek. Zastanów si,
co si stao, aby móc w przyszoci unikn powtórzenia tej sytuacji.

Lektura uzupeniajca

Mnóstwo cennych informacji na temat usuwania bdów mona znale w ksikach Steve’a
Maguire’a Writing Solid Code (Microsoft Press, 1993) i Steve’a McConella Kod doskonay
(Helion, 2010).

background image

Skorowidz

Kobieta: Czy jest tu moja ciotka Minnie?

Driftwood: Có, moesz wej i poszuka, jeeli chcesz.

Jeli jej tu nie ma, to zapewne moesz znale kogo równie dobrego.

Bracia Marx

, Noc w operze

#define, 31
#ifdef, 207
%f, 128
%lf, 128
&, 17
.length, 32
?, 12, 18
|, 17
++, 19, 22
+=, 109
<=, 24
==, 17
0, 31

A

abstrakcja, 112, 208
addfront, 55
aktualizacja komentarza, 35
algorytm, 8, 193

czas dziaania, 50
dane wejciowe, 44
jasny, 86
Markowa, 70, 72, 79, 90

test, 168

podstawowy, 39, 83
porównywanie czasu dziaania, 50
przeszukiwania,

binarnego, 41
sekwencyjnego, 40

przyspieszanie, 181
rola, 39
sortowania, 42, 47
tworzenia,

acuchów elementów, 166
tekstu, 85

usuwania nieuytków, 116
wybór, 68, 182
wymagania pamiciowe, 50
wyszukiwania binarnego, 42
zakoczenie, 77
zoono,

oczekiwana, 50
pesymistyczna, 50

alokacja, 116

pamici, 24, 166, 186, 192

analiza

projektu, 8
skadniowa drzewa, 63

ANSI, 202

C, 46, 53, 202, 204

standard, 24

API, 113, 204
application programming interface, 113
argumenty makra, 29
Ariane 5, 165
arytmetyczne

przesunicie, 200

asembler, 188
asercja, 150

background image

260

SKOROWIDZ

asocjacyjna

tablica, 86

associative array, 86
atexit, 116
automatyzacja, 7, 254

testów, 157

Awk, 9, 86, 87, 90, 158, 180, 193, 235, 237, 245

B

backwards compatibility, 215
bajty

kolejno, 201
porzdek, 211

balanced tree, 61
B-drzewo, 63
Beta wersja, 168
bezwzgldna

warto, 49

biaa skrzynka, 167
biblioteka, 202
big-endian, 218
binarne

przeszukiwanie, 46
drzewo poszukiwa, 59, 60

bitowy

operator, 17
pole, 201

bd

asercja, 150
bdne przekonanie, 136
cechy usterki, 132
diagnostyka, 127
dodanie instrukcji wywietlajcych informacje, 132
dziennik, 134
informacja, 151
innych programistów, 143
kompilatora, 143
komunikat, 118
minimalny zestaw danych wejciowych, 132
na danie, 131
nieregularny, 138
nowy, 129
obsuga, 99, 101, 117
po zmianie, 129
porównywanie plików, 135
powielenie, 129
przepenienia bufora, 164
roku 2000, 188
rozmowa z pluszowym misiem, 131
rzeczywiste dziaanie programu, 137
skadni, 21
skutki lekcewaenia, 130
sprztu, 138
strumie, 134
u jednej osoby, 140

usuwanie, 125, 147
uwane przeczytanie kodu, 131
wykres, 134
wykrywanie, 9
wymuszanie powtarzalnoci, 131
zasada obsugi, 119
znajdowanie, 147
znany, 144

boundary condition testing, 148
Bourne, 166
break, 27
Brooks, 69, 95
bsearch, 46
bucket, 64
bufor

bd przepenienia, 164
danych,

wejciowych, 187
wyjciowych, 187

rozmiar, 76

bug, 125
build, 76

C

C, 9, 10, 17, 19, 22, 24, 27, 28, 31, 32, 40, 44, 48, 53,

54, 64, 66, 73, 81, 83, 89, 96, 103, 107, 114, 116,
121, 134, 139, 160, 177, 182, 184, 188, 189, 191,
196, 197, 199, 201, 202, 203, 213, 217, 231, 243
wada, 79
zaleta, 79

C++, 9, 14, 17, 19, 22, 24, 27, 28, 29, 31, 32, 40, 44,

47, 51, 53, 54, 59, 64, 66, 83, 89, 108, 110, 111,
113, 115, 116, 134, 139, 160, 163, 177, 182, 184, 188,
189, 191, 196, 198, 199, 201, 202, 213, 217, 243

case, 26
cel testowania, 167
cerr, 134
Chain, 80
char, 200
char **array, 40
clock, 177
Cohen, 218
comma-separated values, 94
Comparable, 47
const, 31
cost model, 191
cross-referencer, 143
CSV, 94, 95, 96, 108, 112
csvgetline, 96
ctime, 36, 153
ctype, 28
cyclic redundancy check, 67
cykliczna kontrola nadmiarowa, 67
czarna skrzynka, 167

background image

SKOROWIDZ

261

czas

dziaania algorytmu, 50
mierzenie, 172, 177
pracy procesora, 178
uycia procesora, 177
wykonywania programu, 177

czytelne formatowanie, 16

D

dane, 64, 155

globalne, 34
na wyjciu, 155
najmniejszy typ, 189
oznaczanie koca, 77
statyczne, 54
struktura, 8, 39, 59
szkodliwe, 164
typ le dobrany, 128
wejciowe, 187
wybór struktur, 89
wyjciowe, 187
wymiana, 209, 212

Date, 178
debugging, 125
debugowanie, 126, 256
decyzje

wielokierunkowe, 25

defensive programming, 122
defensywne programowanie, 122, 151
definicja,

pakietów, 202
pola, 99

dekrementacja, 19
deque, 84
design patterns, 91
deskryptywna

nazwa, 13

destruktor, 116
diagnostyka

bdów, 127
instrukcji, 127
kodu, 9
programu, 126, 140

diff, 135
Dijkstra, 147
dugo sów, 85
dobry

interfejs, 112
kod, 37
technika sortowania, 63
zestaw testów, 161

domylny rozmiar tablicy, 73
dowiadczenia, 253
double, 187

do-while, 23
drukowanie elementów listy, 56
drzewo, 59

analiza skadniowa, 63
korze, 59
niezrównowaone, 61
poszukiwa binarne, 59, 60
przegldanie poprzeczne, 62
zrównowaone, 61

dublowanie elementów, 61
dwuznacznoci unikanie, 16
dzieci wze, 60
dzielenie, 59
dziennik

bd, 134

E

efekty uboczne, 19
efektywno wykorzystania pamici, 190
elastyczno, 108
element

dostp swobodny, 59
dublowanie, 61
grupowanie, 16
liczenie, 57
o zmiennym rozmiarze, 59
powizany, 14, 64
przesuwanie, 53
wstawianie, 59

else, 25, 26
else-if, 25, 26
Ellis, 89
endian, 218
endprintf, 117
enum, 31
EOF, 200
estrdup, 118
ewaluacja, 19, 29
exception, 120

F

fall-through, 26
fclose, 151
fflush, 134
fgets, 24, 148
filtr spamu, 176
final, 31
find, 40
Flandren, 194
float, 187
flush, 134
flushcaches, 249
fopen, 151
for, 22, 23

background image

262

SKOROWIDZ

format

CSV, 94, 95, 96
ptla, 22

formatowanie

czytelne, 16
wyraenia, 16

fprintf, 151
fragment niejasny, 11
fread, 151
free, 192
funkcja

generujca, 81
komentarz, 34
logiczna, 14
acuchowa, 114
mieszajca, 64, 67, 74, 75
nazwa, 13, 14
sortujca, 44

fwrite, 151

G

garbage collection, 116
generate, 242
generator

liczb losowych, 49
odsyaczy, 143
tekstu, 77

getchar, 23, 28
gets, 24, 164
getTime, 178
GIF, 190
globalne

dane, 34
optymalizator, 182
zmiennne, 112

gowa, 54
gówny nurt jzyka, 197
gorcy punkt, 178, 184, 186
graficzne operacje, 188
gramatyka, 238
granice tabeli, 166
grep, 143, 172, 229, 234
grupowanie elementów, 16

H

Hashtable, 79, 83
head, 54
hermetyzacja, 112
hierarchiczna struktura danych, 59
Hoare, 42, 47

I

IBM 7094, 248
idealny komentarz, 33
idiom, 22, 24
idiomatyczny kod, 36
if, 20, 21, 25
if...else, 19, 25
implementacja,

niezalene wyniki, 156
programu, 8

indeksowania operator, 85
indexOf, 40
Inferno, 187
informacja

o bdzie, 151
ukrywanie, 99, 100, 112

inicjalizacja, 114

statyczna, 115
tablica, 167
zmienna, 167

inkrementacja, 16, 19
in-order traversal, 62
insert, 62
instrukcja, 16

diagnostyczna, 127
sprawdzajca, 26

Integer, 48
interaktywnego programu test, 168
interfejs, 8, 47, 96, 99, 112, 208, 254, 256

CSV, 112
do tablic rozproszonych, 64
dobry, 112
duy, 113
atwy w uyciu, 123
poprawny, 150
programistyczny, 113
publiczny, 80, 108
uytkownika, 9, 121
zasady tworzenia, 112
zwizy, 113

internacjonalizacja, 216
internationalization, 216
internetowy robak, 165
interpreter, 237

polece, 234

isspam, 179
isupper, 28

J

jasny algorytm, 86
Java, 9, 14, 17, 22, 24, 27, 28, 31, 40, 47, 48, 51, 54,

58, 64, 79, 83, 89, 113, 115, 116, 121, 134, 178,
188, 199, 213

Java Virtual Machine, 242
jednokierunkowa lista, 54

background image

SKOROWIDZ

263

jednolito, 123
jzyk

may, 222
niskiego poziomu, 9, 188
nurt gówny, 197
programowania, 9
skryptowy, 236
standard, 196
wybór, 221
wysokiego poziomu, 9

JIT, 247
just in time compilation, 247
JVM, 242

K

klamry, 27
klarowno, 26, 253
klasa, 201

globalna, 13
kontenerowa, 79

klucze, 64
Knuth, 167, 178, 194
kod

diagnostyka, 9
dobry, 37
generowanie za pomoc makr, 246
idiomatyczny, 36
klarowny, 19, 36
atwo czytania, 12
nizany, 240
optymalizacja, 182
pokrycie testami, 156
przejrzysty, 18
regulacja, 183
samosprawdzajcy, 133
spójny, 12
sprytny, 18
struktura, 16

uwypuklenie, 20

testowanie w czasie pisania, 151
wolny od bdów, 147
wyszej jakoci, 151
zaleny od maszyny, 188
zwizy, 19, 86
ródowy, 12

Koenig, 245
kolejka, 14

dwukierunkowa, 84

kolejno,

bajtów, 201
wykonywania oblicze, 199

kolizja, 67
komentarz, 33, 34

aktualizacja, 35
cel stosowania, 37

funkcja, 34
idealny, 33
niejasny, 37

kompilacja

na czas, 247
w locie, 247
warunkowa, 205

kompilator, 166, 182, 184, 195, 197, 243, 250

bd, 143
optymalizacji kodu, 182
testowanie, 155, 201

komputer zasady korzystania, 7
komunikat, 217

o bdzie, 118

konflikt nazw, 113
konstruktor, 115, 116
kontener, 83
konwencje, 12
konwersji wspóczynnik, 29
kocowy warunek, 149
kopiowanie, 59, 114
korze drzewa, 59
kosztów model, 191
krotka, 120
kubeek, 64

L

last-in-first-out, 59
liczba, 29, 31

0, 31
cakowita, 45, 191
double, 128
losowa, 49
zmiennoprzecinkowa, 191

liczenie elementów, 57
licznik odniesie, 116
LIFO, 59
liniowe przeszukiwanie, 40
lista, 54, 83

drukowanie elementów, 56
jednokierunkowa, 54
modyfikacja, 55
pami wolna, 186
tworzenie, 55
usuwanie, 57, 58

li, 61
literate programming, 245
little languages, 222
locality, 186
Locanthi, 246
logiczne przesunicie, 200
lokalnoci zasada, 186
lookup, 62
losowa liczba, 49

background image

264

SKOROWIDZ

acuch

algorytm tworzenia, 166
nazwa, 13
Markowa , 70, 79

acuchowa funkcja, 114
atwy w uyciu interfejs, 123

M

mainstream, 197
makro, 28, 31, 32

argumenty, 29
generowanie kodu, 246
problem, 28

malloc, 24, 129, 192
mae jzyki, 222
map, 79, 84, 85
markov, 70, 91, 163, 170
maszyna,

stosowa, 240
wirtualna, 237

Math.abs, 49
mechanizm wyjtków, 120
memcmp, 179, 183
memcopy, 53
memcpy, 113
memmove, 53, 113, 188
memset, 161, 188
metacharacters, 228
metaznaki, 228
Microsoft Visual C++ 5.0, 163
mierzenie czasu, 172, 177
mieszajca funkcja, 74
Mitchell, 89
mocy zmniejszenie, 184
model,

kosztów, 191
statystyczny tekstu, 70

Modula-3, 243
modularyzacja, 112

N

nadmiarowa kontrola cykliczna, 67
najmniejsze typy danych, 189
najprostsza struktura danych, 53
najwspanialsze osignicie informatyki, 64
Nameval, 51
NaN, 120
nawiasy, 16

klamrowe, 20

nazwa, 13

deskryptywna, 13
elementy powizane, 14

funkcja, 14

logiczna, 14

klasa globalna, 13
konflikt, 113
acuch, 13
niespójna, 14
prywatna, 113
staa, 13
struktura globalna, 13
wskanik, 13
zmienna,

globalna, 13
lokalna, 13
ptlowa, 13

negacja, 35
new, 129
niedorzeczne wartoci, 128
niejasny

fragment, 11
komentarz, 37

niepoprawne dane wejciowe, 122
nieprzezroczysty typ, 112
niesychanie dua warto, 128
niespójna nazwa, 14
nietypowe sytuacje, 120
niezalene implementacje, 156
niezamykanie plików, 138
niezrównowaone drzewo, 61
niskopoziomowy jzyk, 9
nizany kod, 240
not a number, 120
notacja, 221, 254

O, 50
programowanie, 9

nowy wze, 61
null, 32
numerycznego programu test, 155
nurt gówny jzyka, 197
nvcmp, 46

O

obcieniowe testy, 9
obiektu rozmiar, 32
Object, 47, 48
obliczenia

kolejno wykonywania, 199
zawczasu, 187

obsuga bdów, 99, 101, 117

zasada, 119

oczekiwana zoono algorytmu, 50
odsyaczy generator, 143
odzyskiwanie zasobów, 116
ogonowa rekurencja, 62
ogólno, 253

programowania, 7

background image

SKOROWIDZ

265

on the fly compilation, 247
O-notation, 50
operacja

graficzna, 188
wejcia, 19
wyjcia, 19

operator, 16

bitowy, 17
indeksowania, 85
logiczny, 17
priorytet, 17
przecianie, 189
przypisania, 17
relacji, 17, 24

opónienia w dostarczaniu poczty, 172
optymalizacja, 184, 193

gospodarowania pamici, 189
kodu kompilatora, 182
wykorzystania zasobów, 9
zasada, 171

optymalizator globalny, 182
oszczdzanie pamici, 190
oznaczanie koca danych, 77

P

pair, 120
pakietów definicja, 202
pami, 114

alokowanie, 24, 166, 186, 192
efektywno wykorzystania, 190
optymalne gospodarowanie, 189
oszczdzanie, 190
podrczna, 186
wolna, 186
wyciek, 138
zwalnianie, 192

Pathfinder, 130
Perl, 9, 86, 87, 90, 237
pesymistyczna zoono algorytmu, 50
ptla, 16, 21, 22, 23, 24, 148

eliminacja, 185
format, 22

pierwsze wystpienie znaku, 40
pisanie kodu, 151
pimienne programowanie, 245
plik

dziennika, 134
nagówkowy, 202
niezamykanie, 138

poczty opónienia w dostarczaniu, 172
podrczna pami, 186
podstawowe algorytmy, 39, 83
pole

bitowe, 201
definicja, 99

pomiary, 193

wykonywanie, 172

poprawa wydajnoci, 175
poprawno interfejsu, 150
porównywanie

czasu dziaania algorytmów, 50
liczb cakowitych, 45

portability, 195
Portable Operating System Interface, 218
porzdek bajtów, 211
POSIX, 204, 218
post-order traversal, 63
PostScript, 245
potok, 249
potomek, 60, 61
powizane elementy, 64
pozycja znaku, 29
PPM, 190
praktyka programowania, 7, 12
Prefix, 81, 82
pre-order traversal, 63
printf, 97, 128, 222
priorytetu operator, 17
problemu rozmiar, 50
procedura przeszukujca, 40
procesor, 195
prof, 178
profil, 172, 173, 178
program

diagnostyczny, 126, 140

wady, 127
zalety, 126

do powszechnego uytku, 90
generujcy tekst, 69
graficzny, 155
implementacja, 8
interaktywny, 168
jak napisa, 12
numeryczny, 155
odporny na niepoprawne dane wejciowe, 122
pisze programy, 242
profilujcy, 172, 173,178
prototyp, 98
przekazanie do uytku, 166
przenony, 9, 195
przyspieszanie dziaania, 183
rzeczywiste dziaanie, 137
spowolnienie, 189
struktura, 143
wamanie, 164
wydajno, 88, 188
zoono obliczeniowa, 181

programowanie

defensywne, 122, 151
notacja, 9
ogólno, 7

background image

266

SKOROWIDZ

programowanie

pimienne, 245
praktyka, 7, 12
prostota, 7
przejrzysto, 7
styl, 8, 38
zasady, 12

projektu analiza, 8
prostota programowania, 7, 253
prototyp, 197

programu, 98

prywatna nazwa, 113
przechowywanie elementów o zmiennym rozmiarze, 59
przecianie operatorów, 189
przegldanie

poprzeczne, 62
wsteczne, 63
wzdune, 63

przejrzysto, 13

programowanie, 7

przekazanie programu do uytku, 166
przenono programów, 9, 142, 195, 214, 257
przepenienie, 46

bufora, 164

przesunicie

arytmetyczne, 200
elementu, 53
logiczne, 200

przeszukiwanie

binarne, 41, 46
liniowe, 40
procedura, 40
sekwencyjne, 40
tablicy, 154
tekstu, 143

przydzielanie pamici, 114
przypisanie, 16

operator, 17
wstawianie do warunku ptli, 23

przyspieszanie

algorytmu, 181
dziaania programu, 174, 183
struktury danych, 181

publiczny interfejs, 80, 108
puapki jzykowe, 198
punkt gorcy, 184, 186
putchar, 23

Q

qsort, 44, 45, 46
queue, 14
quicksort, 42, 49

R

rama testowa, 154, 159, 162, 193
rand, 49
RCS, 135
real, 177
realloc, 129
reduction in strength, 184
reentrant, 116
reference count, 116
referencja, 115
regression testing, 157
regresywne testowanie, 157, 180, 184
regulacja kodu, 183
regular expressions, 228
regularne wyraenia, 228
rekurencja, 47

ogonowa, 62

relacji operator, 17, 24
reputacji utrata, 143
rgen, 49
robak internetowy, 165
rozmiar

bufora, 76
obiektu, 32
problemu, 50
tablicy, 29, 33, 66, 104
typów danych, 198

rozszerzalna tablica, 51
rozwój, 253
rzutowanie, 53

S

samodzielne testy, 158
samosprawdzajcy si kod, 133
scalanie, 59
scanf, 96, 128, 151
scmp, 45
sekwencyjne wyszukiwanie, 40
sentinel, 77
shaney, 91
sizeof, 32
skadni bdy, 21
skrócenie czasu usuwania usterek, 125
skrypt testowy, 158
skryptowy jzyk, 236
sowa, 73, 85
sownik, 84, 87

struktura danych, 79

sort, 47, 49
sortowanie

algorytm, 42, 47
dobra technika, 63
funkcja, 44
szybkie, 42
tablic acuchów, 45

background image

SKOROWIDZ

267

spam, 172

filtr, 176

specyfikacja, 101

zawarto, 101

split, 103, 105, 109
sposoby doboru testów, 154
spójno, 20, 22, 114

kodu, 12
zewntrzna, 114

sprztu bd, 138
staa, 19, 31

cakowitoliczbowa, 31
nazwa, 13
znakowa, 31

stanu utrzymywanie, 114
standard, 197, 202

ANSI C, 24, 202, 222, 225
ANSI/ISO jzyka C, 196
ISO jzyka C++, 196
jzyka, 196

Standard Template Library, 83
State, 73
statyczna inicjalizacja, 115
statyczne dane, 54
stderr, 134
stdout, 113
STL, 59, 83, 90, 120, 163
stos, 59, 186

wywoa, 126, 130

strchr, 40, 179
strcmp, 36, 45
strcpy, 24
strdup, 24
StreamTokenizer, 80
strerror, 120
String, 40, 48
strings, 140
strlen, 24, 179
strncmp, 179
stronicowanie, 189
strstr, 40, 173, 176, 179
strtok, 96, 105, 113
struktura

danych, 8, 39, 201

najprostsza, 53
sownik, 79

globalna nazwa, 13
kodu, 16
programu, 143

strumienie bdów, 134
styl, 12, 255

funkcja, 12
programowania, 8, 38

swap, 49
Swift, 218
swobodny dostp do elementów, 59

symbole,

tablica, 64
wieloznaczne, 228

SYS, 177
system

zalenoci, 208
operacyjny, 195

System.err, 134
systematyczne testowanie niewielkich przypadków, 154
sytuacje nietypowe, 120
szkodliwe dane wejciowe, 164
szybkie sortowanie, 42

T

tabela

granice, 166

tablica, 40, 53

asocjacyjna, 86
domylny rozmiar, 73
inicjalizacja, 167
acuchów, 45
mieszajca, 51, 64, 80

funkcja tworzca, 75

przeszukanie, 154
rozmiar, 29, 33, 66, 104
rozproszona, 64
rozszerzalna, 51
sowa, 73
symboli, 64
znaków, 108

tail recursion, 62
Tcl/Tk, 9
technika usuwania bdów, 125
tekst

algorytm tworzenia, 85
generowanie, 77
model statystyczny, 70
przeszukiwanie, 143

test, 9, 147, 153, 193, 256

algorytm Markowa, 168
automatyzacja, 157
biaej skrzynki, 167
cel, 167
czarnej skrzynki, 167
dobry zestaw, 161
dua iloci danych, 163
kompilator, 155
obcieniowy, 9
pokrycia kodu, 156
programu,

graficznego, 155
interaktywnego, 168
numerycznego, 155

przecieniowy, 163
rama, 154, 159, 162

background image

268

SKOROWIDZ

test

regresywny, 157, 180, 184
samodzielny, 158
sposoby doboru, 154
stopniowy, 153
systematyczny, 153
testu, 168
ustawienia parametrów wejciowych, 167
w czasie pisania kodu, 151
wartoci brzegowych, 9, 148

rozszerzenie metody, 154

wzorcowy, 194
zautomatyzowanie, 154
zestaw, 153, 167, 174

TEX, 167
Thompson, 194, 248
threaded code, 240
time, 177
tuple, 120
tworzenie listy, 55
typ danych

najmniejszych, 189
nieprzezroczysty, 112
rozmiar, 198
le dobrany, 128

U

uboczne efekty, 19
ukrywanie informacji, 99, 100, 112
unia, 201
Unicode, 216
unikanie dwuznaczno, 16
unquote, 96
unsigned char, 66
ustawianie wartoci pocztkowych, 115
usterki czas usuwania, 125
usuwanie

bdów, 147
listy, 57, 58
usterek, 125

UTF-8, 217
utrata reputacji, 143
utrzymywanie stanu, 114
uytkownika interfejs, 9, 121

V

Vector, 79, 83, 84, 108
Visual Basic, 9, 243
void*, 44, 53

W

wartoci

bezwzgldne, 49
brzegowych testowanie, 9
niedorzeczne, 128
niesychanie due, 128
oddzielane przecinkami, 94
pocztkowych ustawianie, 115
zmiennej modyfikacja, 19

wartownik, 77
warunek, 25

brzegowy, 148
kocowy, 149
ptli, 23
wstpny, 149

warunkowa,

kompilacja, 205
wyraenie, 19

wcicia, 16, 20, 21
wczytywanie liczb typu double, 128
wejcie, 19
wektor, 83
weprintf, 61, 117
wersja beta, 168
wze

dzieci, 60
nowy, 61

while, 23, 26
wielokierunkowe decyzje, 25
wielowejciowy program, 116
wildcards, 228
wiszcy wskanik, 139
wamanie do programu, 164
waciwoci danych wejciowych, 155
wprintf, 203
wskanik

brakujcego potomka, 60
nazwy, 13
wiszcy, 139

wspóczynnik konwersji, 29
wspódzielenie, 114
wstawianie elementu, 59
wsteczna zgodno, 215
wstpny warunek, 149
wybór

algorytmu, 68, 182
jzyka, 9, 221
struktur danych, 89

wycieki pamici, 138
wydajno, 171, 257

analiza graficzna, 180
poprawa, 175
program, 88, 188

wyjtek, 120
wyjcie, 19

background image

SKOROWIDZ

269

wykadnicza zoono obliczeniowa, 51
wykonywanie pomiarów, 172
wykorzystania zasobów optymalizacja, 9
wykres bdów, 134
wykrywanie bdów, 9
wymagania pamiciowe algorytmu, 50
wymiana danych, 209, 212
wyniki niezalenych implementacji, 156
wyraenia, 16

formatowanie, 16
regularne, 228
skomplikowane, 17
warunkowe, 19

wysokiego poziomu jzyk, 9
wyszukiwanie

binarne, 42
sekwencyjne, 40

wywoanie

stos, 126, 130

wzorzec projektowy, 91

Y

Yorktown, 150, 151

Z

zalenoci systemowe, 208
zarzdzanie zasobami, 58, 99, 100, 114
zasada

korzystania z komputera, 7
lokalnoci, 186
obsugi bdów, 119
optymalizacji, 171
programowania, 12

zasoby

odzyskiwanie, 116
zarzdzanie, 58, 99, 100, 114

zautomatyzowanie testowania, 154
zbiór, 83

klas kontenerowych, 79

zero, 31
zestaw

testów, 153, 167, 174
znaków, 216

zewntrzna spójno, 114
zgodno wsteczna, 215
zoono obliczeniowa, 50, 56, 181

wykadnicza, 51

zmienna, 103

globalna, 13, 112
inicjalizacja, 167
lokalna, 13
modyfikacja wartoci, 19
nazwa, 13
ptlowa, 13
wewntrzna, 103

zmniejszenie mocy, 184
znak

pierwsze wystpienie, 40
pozycja, 29
tablica, 108
zapytania, 12
zestaw, 216

zrównowaone drzewo, 61
zwalnianie pamieci, 114, 192
zwikszenie wydajnoci programu, 188
zwizo, 13

kodu, 86

background image

Wyszukiwarka

Podobne podstrony:
Lekcja programowania Najlepsze praktyki prapro
Lekcja programowania Najlepsze praktyki prapro
Lekcja programowania Najlepsze praktyki 2
Lekcja programowania Najlepsze praktyki
Lekcja kopia, Najlepsza lekcja historii
Najlepsze praktyki upadłości konsumenckiej
Program zajęć Praktyczna stylistyka, RÓŻNE
PLAN UE DOT NAJLEPSZYCH PRAKTY Nieznany
program zajec praktycznych tech elektr
Lekcja 10, ArchiCAD, praktyczny kurs on-line
Program publicystyczny w praktyce magazyn$ godziny
Lekcja 15, ArchiCAD, praktyczny kurs on-line
2014 2015 PROGRAM ZAWODOWYCH PRAKTYK STUDENCKICH
analiza trendow i najlepszych praktyk
Lekcja 13, ArchiCAD, praktyczny kurs on-line
ramowy program stazu praktyki, 3 eln

więcej podobnych podstron