Błąd (informatyka)

Z Wikipedii, wolnej encyklopedii

Błąd oprogramowania lub w żargonie informatycznym bug (czytaj bag ) – usterka programu komputerowego powodująca jego nieprawidłowe działanie, wynikająca z błędu człowieka na jednym z etapów tworzenia oprogramowania, zwykle podczas tworzenia kodu źródłowego, lecz niekiedy także na etapie projektowania.

Etymologia angielskiego określenia bug[edytuj | edytuj kod]

Pierwsza komputerowa „pluskwa” usunięta z komputera Mark II

Słowo bug (z ang. pluskwa, owad, robactwo) przeszło prawdopodobnie do żargonu programistycznego z żargonu inżynierów telekomunikacji, którzy żartowali na temat szumów w sygnale, mówiąc, że „owady zalęgły się w urządzeniu”. Wiadomo też, że słowa bug w kontekście usterki użył Thomas Edison już w 1878[1].

Wprowadzenie do użycia wspomnianego terminu przypisywane jest też pani admirał Grace Hopper, choć pewne źródła negują jej udział w poniższej historii. Podczas prac prowadzonych 9 września 1947 r.[2] z komputerem Harvard Mark II stwierdzono jego nieprawidłowe działanie, a po poszukiwaniach przyczyny operatorzy, m.in. William „Bill” Burke znaleźli w przekaźniku 70. panelu F ćmę (ang. moth), która powodowała spięcie. Owad został usunięty i wklejony do dziennika z wpisem o ćmie przypisywanym Grace Hopper – fotografia obok. Dziennik do 1991 roku znajdował się w Naval Surface Warfare Center Computer Museum w Dahlgren w stanie Wirginia (USA), a obecnie w The Smithsonian Institute National Museum of American History. Opis fotografii tego dziennika podaje błędny rok wpisu – 1945, inne źródła wskazują na rok 1947, co potwierdza fakt, iż komputer Mark II został uruchomiony w lipcu tego roku.

Słowo bug jest często tłumaczone w tym kontekście jako pluskwa. Pluskwa oznacza obecnie również podsłuch lub podgląd elektroniczny (mikrofon, kamera) lub analogicznie backdoor celowo zaimplementowany w oprogramowaniu z inicjatywy programisty lub na zlecenie.

Błędy programistyczne są przedmiotem wielu spośród tzw. praw Murphy’ego, m.in. prawo nieskończoności Lubarskiego „w każdym programie (dłuższym niż 100 linijek) jest jeszcze jeden błąd”[3].

Diagnoza i usuwanie[edytuj | edytuj kod]

 Osobny artykuł: Debugowanie.

Bug jako określenie błędu programistycznego występuje w nazwach programów pomagających usuwać błędy, tzw. debugerów, czy też „odpluskwiaczy”. Programy te pozwalają śledzić wartości określonych zmiennych i rejestrów wykorzystywanych w programie do momentu wystąpienia błędu, co z kolei pozwala znaleźć dokładne miejsce w kodzie źródłowym, w którym należy dokonać poprawek.

Aby ułatwić zgłaszanie błędów testerom i użytkownikom oraz w celu śledzenia stanów błędów przez wszystkich zainteresowanych, powstały liczne systemy śledzenia błędów. Do jednych z nich należy Bugzilla (stworzony pierwotnie na potrzeby projektu Mozilla), do listopada 2014 r.[4] stosowana przez fundację Wikimedia do zbierania informacji o błędach w oprogramowaniu Wikipedii i pokrewnych Wiki (została zastąpiona przez Phabricatora). W systemie Bugzilla każdy może zgłosić błąd, podając przy tym okoliczności, w jakich on występuje. Zgłoszenie to jest następnie przydzielane określonemu programiście, a aktualne informacje o postępach w naprawianiu usterki są udostępniane w systemie.

Typy błędów[edytuj | edytuj kod]

Z reguły wyróżnia się trzy główne typy błędów:

  • Błędy składniowe – nie pozwalają na kompilację programu, jak np. literówka w nazwie zmiennej lub wywołaniu funkcji. Są one wykrywane przez kompilator i najczęściej dość łatwe do usunięcia. Zazwyczaj wynikają z drobnych pomyłek programisty.
  • Błędy semantyczne (znaczeniowe) – część błędów semantycznych można wychwycić już w momencie kompilacji, np. próbę odczytania wartości niezainicjowanej zmiennej, lecz inne mogą ujawnić się dopiero w trakcie wykonywania.
  • Błędy logiczne – nie przerywają kompilacji, lecz powodują niewłaściwe działanie warstwy logicznej jak np. niepoprawne wyznaczanie pozycji gracza (które także może być spowodowane literówką – jak np. wpisanie znaku „+” zamiast „-”). Ten typ błędów jest znacznie trudniejszy do wykrycia i usunięcia; często błąd tkwi w jednym źle zapisanym znaku, lecz programista musi do tego znaku sam dojść (w przypadku błędu składniowego znak jest wskazywany przez komunikat kompilatora).

Zapobieganie błędom[edytuj | edytuj kod]

W typowych warunkach można się spodziewać, że w każdym nietrywialnym programie będą błędy. Liczbę błędów można też ograniczyć przeprowadzając testy programu. Testy te powinny być w miarę możliwości zautomatyzowane – komputer potrafi przeprowadzić o kilka rzędów wielkości więcej testów na godzinę niż człowiek.

Do metod zmniejszania liczby błędów można zaliczyć:

  • umiejętne zastosowanie paradygmatów programowania strukturalnego, proceduralnego i obiektowego,
  • pisanie w sposób czytelny, hierarchiczne formatowanie kodu źródłowego
  • unikanie skrótów programistycznych w rodzaju ++i*=*c--;[5]
  • stosowanie zrozumiałych identyfikatorów, nawet kosztem ich większej długości
  • stosowanie komentarzy w miejscach, których zrozumienie kodu nie jest natychmiastowe
  • współtworzenie programu i jego dokumentacji
  • opisywanie (w komentarzach i dokumentacji) założeń przyjętych podczas pisania danego fragmentu kodu (np. co do typów danych wejściowych, czy spodziewanego sposobu użycia)
  • unikanie trudnych w analizie konstrukcji (jak instrukcja skoku, czy ewaluacja kodu w trakcie wykonania)
  • używanie narzędzi wykrywających podejrzane fragmenty kodu (np. lint), włączenie ostrzeżeń kompilatora o napotkaniu konstrukcji będących częstym źródłem błędów (np. if(a=b)... zamiast if(a==b)...)
  • ręczne audyty kodu

Czasem błędy wykrywa się przez wprowadzanie do programu losowych danych i sprawdzanie otrzymywanych odpowiedzi. Ponieważ typowe błędy dotyczą wielu danych, wykrywa się w ten sposób większość błędów.

Bardzo rzadko przeprowadza się dowody matematyczne programów. Nawet one nie dają jednak gwarancji poprawnego działania programu, ponieważ nie jest pewne, że model zachowania programu jest bezbłędny (jeśli ta sama osoba pisała kod i dowód, to ten sam błąd mógł się pojawić w obu), ani też, że zastosowany model matematyczny odpowiada rzeczywistości (np. kompilator czy nawet sam procesor może wprowadzić optymalizacje, które psują „poprawny” kod).

Ponieważ testowanie dużych czynności jest trudną operacją, zwykle testuje się osobno podzespoły programu oraz program w całości (zakładając przy tym, że podzespoły działają poprawnie). Można przez to przeoczyć pewną klasę błędów.

Często trudno jest testować program w naturalnym środowisku (np. w przypadku programów sieciowych, operujących bezpośrednio na sprzęcie czy wymagających interakcji z wieloma użytkownikami) i dlatego konieczne jest testowanie w środowisku sztucznym – za pomocą emulatorów sprzętu, sieci czy sztucznego generowania zdarzeń symulujących działania użytkowników („wpisano X w pole Y”, „kliknięto przycisk Z” itp.).

Testy pisane są zwykle w późnej fazie rozwoju oprogramowania. W metodologii zwanej „programowaniem ekstremalnym” testy pisze się zanim rozpocznie się pisanie danej części oprogramowania, co ma zmniejszyć liczbę błędów. Wiąże się to ze zjawiskiem – stwierdzonym empirycznie i znanym z literatury specjalistycznej – wiązki błędów. Oznacza to, że im więcej odkryto błędów w programie, tym większe jest prawdopodobieństwo istnienia błędów niewykrytych. To zaskakujące stwierdzenie można wyjaśnić w następujący sposób: jeśli w programie wykryto dużo lub bardzo dużo błędów, to jest on prawdopodobnie źle napisany, zatem łączna liczba błędów może być większa niż liczba wykrytych. W tym kontekście wczesne wykrywanie błędów (czyli złego programowania) pozwala na uniknięcie tego zjawiska.

Do tworzenia testów i zarządzania nimi istnieje wiele systemów, tzw. testing frameworks, takich jak XUnit.

Zobacz też[edytuj | edytuj kod]

Przypisy[edytuj | edytuj kod]

  1. Edison to Puskas, 13 November 1878, Edison papers, Edison National Laboratory, U.S. National Park Service, West Orange, N.J., cited in Thomas P. Hughes, American Genesis: A History of the American Genius for Invention, Penguin Books, 1989, ISBN 0-14-009741-4, s. 75.
    It has been just so in all of my inventions. The first step is an intuition, and comes with a burst, then difficulties arise – this thing gives out and [it is] then that „Bugs” – as such little faults and difficulties are called – show themselves and months of intense watching, study and labor are requisite before commercial success or failure is certainly reached..
  2. Susan Schuppli, Of Mice Moths and Men Machines, Cosmos and History: The Journal of Natural and Social Philosophy, Vol 4, No 1-2 (2008), ISSN 1832-9101 pdf.
  3. Jeden z wielu zbiorów praw Murphy’ego rozsianych po Internecie [dostęp 2015-09-23].
  4. Quim Gil: Welcome to Phabricator, Wikimedia’s new collaboration platform. 2014-11-24. [dostęp 2015-09-22]. (ang.).
  5. (fragment poprawnego, aczkolwiek nieczytelnego kodu w języku C, oznacza zwiększenie i o jeden, przemnożenie i przez element wskazywany przez wskaźnik c, a następnie przesunięcie wskaźnika c o jeden element do tyłu w tablicy).

Linki zewnętrzne[edytuj | edytuj kod]