Jeśli kodujesz w C, Objective-C lub C ++, możesz użyć CLang Static Analyzer, aby skrytykować swoje źródło bez faktycznego uruchamiania go.
Dostępnych jest kilka narzędzi do debugowania pamięci: ValGrind, Guard Malloc w systemie Mac OS X, Electric Fence w * NIX.
W niektórych środowiskach programistycznych dostępna jest opcja debugowania alokatora pamięci, który wykonuje takie czynności, jak wypełnianie nowo przydzielonych stron i nowo uwolnionych stron śmieciami, wykrywanie zwolnienia nieprzydzielonych wskaźników oraz zapisywanie niektórych danych przed i po każdym bloku sterty, przy czym debugger jest wywoływany, jeśli znany wzorzec tych danych kiedykolwiek się zmieni.
Jakiś facet na Slashdot powiedział, że czerpie wiele korzyści z jednorazowej zmiany linii źródła w debuggerze. „To wszystko” - powiedział. Nie zawsze stosuję się do jego rad, ale kiedy je mam, okazało się to bardzo pomocne. Nawet jeśli nie masz przypadku testowego, który stymuluje nietypową ścieżkę kodu, możesz zmienić zmienną w swoim debuggerze, aby wziąć takie ścieżki, powiedzmy przez przydzielenie pamięci, a następnie za pomocą debugera ustawić nowy wskaźnik na NULL zamiast adres pamięci, a następnie przechodzenie przez procedurę obsługi błędów alokacji.
Używaj asercji - makro assert () w C, C ++ i Objective-C. Jeśli twój język nie zapewnia funkcji potwierdzenia, napisz ją samodzielnie.
Użyj oświadczeń swobodnie, a następnie pozostaw je w kodzie. Wzywam assert () „Test, który ciągle testuje”. Używam ich najczęściej do sprawdzania warunków wstępnych w punkcie wejścia większości moich funkcji. To jedna z części „Programowania na podstawie umowy”, która jest wbudowana w język programowania Eiffla. Druga część to warunki dodatkowe, to znaczy użycie assert () w punktach zwrotnych funkcji, ale uważam, że nie mam z tego tak dużego przebiegu, jak warunki wstępne.
Możesz także użyć aser, aby sprawdzić niezmienniki klas. Chociaż żadna klasa nie jest bezwzględnie wymagana, aby mieć w ogóle niezmienniki, mają ją najbardziej rozsądnie zaprojektowane klasy. Niezmiennik klasy jest pewnym warunkiem, który jest zawsze prawdziwy, poza funkcjami składowymi, które mogą tymczasowo umieścić obiekt w niespójnym stanie. Takie funkcje zawsze muszą przywracać spójność, zanim powrócą.
Zatem każda funkcja członkowska może sprawdzać niezmiennik przy wejściu i wyjściu, a klasa może zdefiniować funkcję o nazwie CheckInvariant, którą dowolny inny kod mógłby wywołać w dowolnym momencie.
Użyj narzędzia pokrycia kodu, aby sprawdzić, które wiersze źródła są faktycznie testowane, a następnie zaprojektuj testy, które stymulują niezbadane wiersze. Na przykład można sprawdzić procedury obsługi niskiej ilości pamięci, uruchamiając aplikację w maszynie wirtualnej, która jest skonfigurowana z małą ilością pamięci fizycznej i bez pliku wymiany lub z bardzo małą.
(Z jakiegoś powodu nigdy nie byłem wtajemniczony, podczas gdy BeOS mógł działać bez pliku wymiany, był bardzo niestabilny w ten sposób. Dominic Giampaolo, który napisał system plików BFS, nalegał, abym nigdy nie uruchamiał BeOS bez wymiany. Nie robię tego zobacz, dlaczego to ma mieć znaczenie, ale musiał to być jakiś artefakt implementacyjny.)
Powinieneś również przetestować odpowiedź swojego kodu na błędy We / Wy. Spróbuj zapisać wszystkie pliki w udziale sieciowym, a następnie odłącz kabel sieciowy, gdy aplikacja jest obciążona dużym obciążeniem. Podobnie odłącz kabel - lub wyłącz sieć bezprzewodową - jeśli komunikujesz się przez sieć.
Jedną z rzeczy, które szczególnie mnie denerwują, są strony internetowe, które nie mają solidnego kodu JavaScript. Strony Facebooka ładują dziesiątki małych plików JavaScript, ale jeśli żaden z nich nie zostanie pobrany, cała strona się zepsuje. Musi istnieć jakiś sposób albo zapewnić pewną tolerancję na błędy, powiedzmy, ponawiając próbę pobrania pliku, albo zapewnić pewien rozsądny efekt rezerwowy, gdy niektóre skrypty nie zostaną pobrane.
Spróbuj zabić swoją aplikację za pomocą debugera lub komendy „kill -9” na * NIX, gdy jest to w trakcie pisania dużego, ważnego pliku. Jeśli twoja aplikacja jest dobrze zaprojektowana, cały plik zostanie zapisany lub w ogóle nie zostanie zapisany, a może jeśli zostanie napisany tylko częściowo, to co zostanie zapisane, nie zostanie uszkodzone, a zapisane dane będą w pełni użyteczne przez aplikacja po ponownym odczytaniu pliku.
bazy danych zawsze mają dyskowe wejścia / wyjścia odporne na awarie, ale prawie żadna inna aplikacja tego nie robi. Chociaż kronikowane systemy plików zapobiegają uszkodzeniu systemu plików w przypadku awarii zasilania lub awarii, w ogóle nie robią nic, aby zapobiec uszkodzeniu lub utracie danych użytkownika końcowego. Odpowiedzialność za to ponoszą użytkownicy aplikacji, ale prawie żadna inna baza danych nie zapewnia odporności na uszkodzenia.