Największe katastrofy oprogramowania

Przylądek Cape Canaveral na Florydzie. 22 czerwca 1962 roku punktualnie o godzinie 9:26 oficer do spraw bezpieczeństwa naciska czerwony guzik… i rakieta Mariner 1 zostaje zniszczona. Zamontowana na niej pierwsza w historii ludzkości sonda międzyplanetarna miała zbadać Wenus. Zamiast tego szczątki Marinera po 293 sekundach lotu spadły na Karaiby, rozpoczynając tym samym serię spektakularnych katastrof software’owych.
1962 - Mariner 1 - Zaraz po starcie rakieta zbacza z kursu i zostaje zniszczona. Powód: programista pominął w kodzie znak górnego podkreślenia (
1962 - Mariner 1 - Zaraz po starcie rakieta zbacza z kursu i zostaje zniszczona. Powód: programista pominął w kodzie znak górnego podkreślenia (

Tydzień później eksperci NASA znaleźli przyczynę: programista zapomniał przenieść znaku ” ̄” z odręcznych notatek do aplikacji sterującej. Dodatkowy bajt kodu służył temu, aby komputer określał pozycję  rakiety, bazując na jej uśrednionej prędkości. Znaku zabrakło, więc parametry były wyliczane na podstawie aktualnych danych, które często się zmieniały. Aby skompensować fluktuacje, procesor nieustannie wysyłał nowe polecenia sterujące, które sprawiały, że Mariner coraz bardziej zbaczał z zaplanowanego kursu. Po niecałych 5 minutach lotu zdecydowano się go zdetonować, aby uniknąć większego nieszczęścia. Nauka płynąca z tej katastrofy przybrała później w NASA postać wewnętrznej notatki: “No detail is too small to overlook” –  żaden szczegół nie jest zbyt mały, aby go przeoczyć.

Kosmos: Rozbicie na skutek błędu

Ponad 30 lat później, 4 kwietnia 1996 roku o godzinie 9:34, na kosmodromie w Kourou pracownik kontroli lotów znów naciska czerwony guzik, niszcząc tym razem Ariane 5. Powód? Rakieta po 37 sekundach dziewiczego lotu zboczyła z kursu, grożąc runięciem na tereny zamieszkane. Również jej szczątki spadły na Karaiby.

Analogie z Marinerem są nie tylko powierzchowne: jak ustaliła speckomisja europejskiej agencji kosmicznej ESA, powód katastrofy leżał w przeciążonym systemie nawigacyjnym SRI, który inżynierowie przenieśli bez adaptacji z poprzednika rakiety, Ariane 4. Przyczynę tej decyzji podano w oficjalnym raporcie: “Panowało przekonanie, że nie byłoby wskazane dokonywanie zmian w softwarze, który tak dobrze funkcjonował w Ariane 4”. Jest to postawa w języku angielskim określana jako: Never touch a running system.

Sęk w tym, że Ariane 5 była nie tylko większa, ale również przyspieszała pięć razy szybciej. SRI musiał więc radzić sobie z wartościami, które nie występowały w przypadku Ariane 4. I tu pojawił się problem: 16-bitowy moduł nie mógł konwertować prędkości wznoszenia się rakiety do wartości całkowitej, ponieważ zapisywano ją w formacie 64-bitowej liczby zmiennoprzecinkowej, a ta na 16 bitach po prostu się nie mieści. Skutek: przepełnienie pamięci, które powodowało nadpisywanie innych zmiennych sytemu. W przypadku poważnego SRI powinien zatrzymać obliczenia i przesyłać na komputer pokładowy Ariane jedynie wartości zmiennych. Jednak ten w dalszym ciągu interpretował odbierane informacje jako dane nawigacyjne. A te mówiły mu, że rakieta ciągle schodzi z kursu. Nanosił więc fatalne poprawki, które doprowadziły do rozbicia rakiety.

Zimna wojna: Maszyny w natarciu

Katastrofy kosmiczne są spektakularne, ale prawdziwymi horrorami okazały się awarie software’owe podczas zimnej wojny. Obydwa mocarstwa polegały wtedy na analizach tworzonych przez komputery i oczywiście były narażone na ich błędy. W 1979 roku amerykański system obronny NORAD zameldował o 2020 atakujących rosyjskich rakietach. Jednak scenariusz był do tego stopnia nieprawdopodobny, że wojskowi natychmiast pomyśleli o błędzie komputera. I tak było w rzeczywistości: procesor NORAD-a na skutek defektu sprzętowego szmuglował w przesyłanych danych przypadkowe bity. Dzięki dodatkowej kontroli błędne wiadomości były odfiltrowywane  – aż do ostrzeżenia o ataku rakietowym.

Niemalże do unicestwienia ludzkości doprowadził meldunek rosyjskiego systemu satelitarnego. 26 września 1983 roku pół godziny po północy komputer pokazał start pięciu amerykańskich rakiet międzykontynentalnych. Znajdujący się w leżącym około 50 km od Moskwy bunkrze “Serpuchow 15” podpułkownik Stanisław Petrow musiał zadecydować, czy ZSRR faktycznie zostało zaatakowane. Jego meldunek stanowiłby podstawę dla sztabu generalnego, aby wydać rozkaz przeciwuderzenia atomowego.

Petrow założył, że to fałszywy alarm: “Miałem takie komiczne uczucie w brzuchu. A poza tym nikt nie zaczyna wojny nuklearnej za pomocą pięciu rakiet”. Błąd znaleziono jeszcze tego samego dnia: satelita zinterpretował odbicia słoneczne na chmurach nad bazą amerykańskich sił powietrznych w Montanie jako start rakiet.

Ale niedowierzanie alarmom komputerowym, jeśli są nieprawdopodobne, może również prowadzić do poważnych błędów, co najlepiej pokazuje odkrycie dziury ozonowej. Na jej trop wpadł brytyjski naukowiec Joe Farman, badając glebę w stacji antarktycznej Halley Bay. W maju 1985 roku opublikował wyniki badań w specjalistycznym czasopiśmie “Nature”.

NASA namierzyła dziurę ozonową już siedem lat wcześniej za pomocą satelitów Nimbus 7. Tylko że wtedy nikt się o tym nie dowiedział. Zamontowane na satelitach sensory TOMS dostarczały 140 000 wartości dziennie, ale software analizujący NASA został tak zaprogramowany, że pomiary zbyt odbiegające od normy 180 Dobson Units (DU) były oznaczane jako “niepewne” i usuwane. Powstałe w ten sposób dziury w strumieniu danych aplikacja wypełniała wartościami bardziej prawdopodobnymi.

Pierwotne wartości pomiarowe drzemały w tym czasie w banku danych do czasu pojawienia się artykułu Farmana. Krótko po tym istnienie dziury ozonowej mogła potwierdzić też NASA – po prostu sięgnęła po “błędy pomiaru” z przeszłości. Dysponując prawidłowo napisanym software’em, mogłaby to uczynić dużo wcześniej.

Megaprojekty: Wylęgarnia awarii

W porównaniu z tymi, do których doszło w wieku XX, katastrofy software’owe ostatnich lat nie były aż tak groźne. Z powodu awarii wielkie projekty, które poniosły klęskę, trafiły wprawdzie na pierwsze strony gazet, ale nie zagroziły ludzkiemu życiu. W przypadku Airbus A380 koncern EADS miał przynajmniej wybór. A to dlatego, że kable były za krótkie.

Największy samolot pasażerski świata został w całości zaprojektowany komputerowo. W Hamburgu powstawała elektronika wraz z okablowaniem, a w Tuluzie kadłub. Gdy latem 2004 technicy zaczęli łączyć elementy elektroniczne za pomocą bez mała 530 kilometrów przewodów (na każdy samolot), okazało się, że w przypadku wielu z nich to się nie uda – kable były za krótkie. Efekt? Koszty się podniosły, a terminy odbioru przesuwały. Rozpoczęta przez jednego z ówczesnych szefów Airbusa, Christiana Streiffa, analiza ujawniła źródło kłopotów z kablami: inżynierowie używali różnych wersji programu CAD CATIA, które nie były ze sobą kompatybilne – edycja 4 w Hamburgu, a 5 w Tuluzie.

Zamieszanie z numerami wersji wydaje się małe. Jednak w rzeczywistości chodzi tu o ogromne różnice jakościowe. Wersję 4 zaprogramowano w Fortranie i przeznaczono do systemu Unix. Wersja 5 została napisana całkowicie na nowo w C++ i można ją było zainstalować tylko w Windows. Różnice dotyczyły więc wręcz niekompatybilnych formatów plików. W efekcie dane nie dawały się bezstratnie konwertować, a metadane – takie jak adnotacje inżynierów do określonych części składowych – przepadały. Airbus miał wprawdzie własne oprogramowanie konwertujące, ale nie funkcjonowało ono prawidłowo

i z tego powodu rzadko go używano.

Właściwy problem leżał według Streiffa na wyższych piętrach koroporacji: “Chodzi o nieprawidłowe działanie kierownictwa, które nie zatroszczyło się wystarczająco o kooperację wewnątrz projektu”. Szef sprzedaży Airbusa John Leahy podaje więcej szczegółów: “Odpowiedzialni ludzie nie zwracali po prostu uwagi na ten problem. Zaniechali przeszkolenia inżynierów na CATIA 5. Nie złagodzili też w Hamburgu niechęci wobec nowej wersji tego programu”. Skutek: dodatkowe koszty w wysokości 5 miliardów euro.

Uwaga: Gdy software myśli

Trwająca latami seria awarii na dobre wstrzymała rozwój A2LL, software’u dla Hartz IV – niemieckiego programu dla bezrobotnych, który pretendował do tego, by stać się modelem socjalu mającym obowiązywać w Europie w niedalekiej przyszłości.

A2LL robił niespodzianki od chwili poczęcia, ale największy zawód sprawił w zimie 2004, kiedy stutysięczny beneficjent Hartza nie otrzymał pieniędzy. Przyczyna była trywialna: krótkie numery konta A2LL dopełniał z tyłu zerami, aby osiągnąć przepisową w niemieckim prawie bankowym liczbę 10 pozycji. Numery te stawały się błędne, ponieważ zera powinny być dopisywane z przodu. Obsługujący operację niemiecki Postbank zwołał sztab kryzysowy, aby przekazywać pieniądze ręcznie. Szło to bardzo wolno, więc jedna z agencji rządowych wpadła na pomysł, żeby zamiast pieniędzy wysyłać beneficjentom czeki. Euforia trwała krótko, ponieważ po kilku dniach stwierdzono, że A2LL z własnej inicjatywy skraca także przydługie nazwy ulic. Skutek: czeków nie można było doręczyć, co omalże nie doprowadziło do zamieszek ulicznych.

W tym czasie A2LL miał w zamawiającej go agencji rządowej opinię przypadku zupełnie beznadziejnego – nie dość, że zawodził w najprostszych operacjach, to jeszcze robił niespodzianki takie jak samodzielne skracanie nazw ulic. Obecnie ta sama agencja opracowuje nowy software. Jego robocza nazwa to “Allegro” – nie ma on jednak nic wspólnego z najpopularniejszym w naszym kraju serwisem aukcyjnym. Przewiduje się, że ukończenie projektu nastąpi za pięć lat, a będzie on kosztował około 90 milionów euro. Czy będzie równie kreatywny jak A2LL – pokaże czas.

Kulejące projekty

Organizacja Standish Group w ramach inicjatywy CHAOS-Studie przebadała od 1994 roku 40 000 projektów IT. Rezultat: udział procentowy tych zakończonych sukcesem rośnie, ale tylko około jednej trzeciej projektów kończy się bez zmiany założeń.

Błędy to norma!

Nawet w dobrze przetestowanych i często usprawnianych programach znajdują się błędy w kodzie. Firma Coverity za pomocą własnego narzędzia, Prevent, badała przez wiele lat 150 dużych opensource’owych projektów, których przeznaczeniem był system Linux i serwer Apache. Ogólnie rzecz biorąc, software przeanalizował 55 milionów linii kodu. Przed trzema laty błąd występował statystycznie co każde 3300 linii; dziś zdarza się średnio co 4000 linii. Oto lista najczęściej pojawiających się błędów:

Typ błęduCzęstość
Pusty wskaźnik wskazuje na używany obszar pamięci 27,95 %
Próba użycia niezwolnionej pamięci25,73 %
Kod programu niedostępny 9,76 %
Próba użycia w kodzie nieprzetestowanych zmiennych8,30 %
Przepełnienie adresowanego statycznie obszaru pamięci6,14 %
Obszar pamięci po zwolnieniu zostanie wykorzystany ponownie 6,46 %
Wyliczone wartości zerowe są używane bez sprawdzenia5,85 %
Zmiennym nie przypisano wartości5,50 %
Wyliczone wartości ujemne są używane bez sprawdzenia3,72 %
Wskaźnik wskazuje na niedostępny obszar pamięci0,62 %
Przepełnienie dynamicznie adresowanego obszaru pamięci0,31 %