Jak uniknąć pułapek analizy statycznej

17

Pracuję w firmie, która uzyska 11 punktów w teście Joela - przynajmniej na papierze.

W praktyce jednak nic nie działa tak dobrze, jak się spodziewano, a projekt działa na DEFCON 1 od pół roku. Teraz większość moich rówieśników jest zadowolona, ​​jeśli mogą wrócić do domu o 18:00 - w niedzielę.

Jedną z pozornie dobrych praktyk, które mnie zaskoczyły, jest brak narzędzi do analizy statycznej. Projekt śledzi zarówno ostrzeżenia gcc -Wall, jak i zastrzeżone i bardzo drogie narzędzie „C / C ++” .

Ostrzeżenia Gcc najczęściej wskazują na prawdziwe (choć przez większość czasu nieszkodliwe) błędy.

Jednak zastrzeżone narzędzia wymieniają takie rzeczy, jak niejawne rzutowania i rozmiar literału łańcuchowego. Niejawne obsady również znajdują się na czarnej liście w ich książce stylów.

Standardową praktyką jest zmuszanie ludzi do zamykania każdego ostrzeżenia. Pamiętaj, że nie wyklucza to ostrzeżeń, które są w większości fałszywie pozytywne, nie stanowi to problemu.

Wynik to:

  1. Ludzie dodają typy rzutów do każdej wartości i każdego argumentu, ukrywając w tym procesie prawdziwe niedopasowania typów.
  2. Ludzie wprowadzają się przez jeden błąd lub używają innej problematycznej funkcji języka (strlen zamiast sizeof, strncpy zamiast strcpy itp.)
  3. Ostrzeżenia zostały wyciszone.
  4. Raporty o błędach zaczynają się pojawiać.

Najważniejsze jest to, że oryginalny kod działał i został napisany przez ludzi, którzy bawili się bezpiecznie w swoich umiejętnościach językowych, podczas gdy poprawki nie były.

Nie sądzę, żeby tę firmę można było uratować. Chciałbym jednak wiedzieć, czy istnieje lepszy, najlepiej działający sposób korzystania z narzędzi „pro” , czy też powinienem po prostu całkowicie ich unikać, na wypadek, gdyby to ja podejmowałem decyzję w przyszłości.

Rozwiązanie, które nie zakłada, że ​​wszyscy programiści są geniuszami, którzy nie mogą się mylić. Ponieważ cóż, jeśli tak, to nie ma potrzeby używania narzędzi w pierwszej kolejności.


źródło
1
Uwaga dodatkowa: GCC oprócz „-Wall” ma również opcję „-Wextra”, a nawet więcej ostrzeżeń, które z jakiegoś powodu nie zostały uwzględnione w obu metaoptycjach. Zobacz dokumentację, aby uzyskać więcej informacji. Ogólnie rzecz biorąc, każda opcja ma wzmiankę, jeśli jest włączona przez metaoption. Aby znaleźć wszystko, co nie jest włączone, możesz wyróżnić w dokumentach zarówno słowa „-Wall”, jak i „-Wextra”, a zobaczysz, który nie jest jeszcze używany.
Cześć Anioł
Dodam też, że zastanawiam się, czy GCC nie włączyło dużo „-Wextra” do „-Wall”. Uwierz mi, niektóre z tych flag są bardzo przydatne ; przynajmniej te ostrzeżenia uwalniają mnie od godzin debugowania.
Cześć Anioł
1
Dziwi mnie, że nikt nie wspomniał o recenzjach kodu w odpowiedziach. Dla mnie ludzie próbujący się przekraść w jakieś kiepskie hacki byliby zablokowani przez recenzje kodu ...
dyesdyes

Odpowiedzi:

16

W praktyce jednak nic nie działa tak dobrze, jak się spodziewano, a projekt działa na DEFCON 1 od pół roku. Teraz większość moich rówieśników jest zadowolona, ​​jeśli mogą wrócić do domu o 18:00 - w niedzielę.

To z pewnością spora część twojego problemu. Inżynier oprogramowania nie może produktywnie pracować dłużej niż 40 godzin tygodniowo. Jeśli przekroczysz ten limit, poważnie zaszkodzisz swojej zdolności do pracy - do tego stopnia, że ​​nawet praca 80 godzin tygodniowo wnosi niewielką wartość do projektu, a czasami projekty mogą nawet cofnąć się, ponieważ zespół wprowadza więcej błędów niż mogą to naprawić. Jeśli spędzasz 60 godzin tygodniowo lub więcej przez pół roku, wtedy cały Twój zespół potrzebuje dobrej długiej przerwy i wrócić po 40 godzinach / tydzień. Nie da się rozwiązać niczego z siłą roboczą, która prawie nie jest w stanie walić w klawiaturę, ponieważ są tak przepracowani.

Jednak zastrzeżone narzędzia wymieniają takie rzeczy, jak niejawne rzutowania i rozmiar literału łańcuchowego. Niejawne obsady również znajdują się na czarnej liście w ich książce stylów.

Naprawdę musisz po prostu całkowicie upuścić narzędzie lub ponownie je skonfigurować / wymienić. Ostrzeżenie przed każdą niejawną obsadą to zdecydowanie za dużo, aby każdy mógł sobie z tym poradzić.

DeadMG
źródło
Czy możesz podać odniesienie do badania dotyczącego limitu około 40 godzin tygodniowo?
11
tu i tutaj , tylko na początek. Jest bardzo dobrze udokumentowane, że nie można wykonać więcej niż 40 godzin tygodniowo produktywnej pracy. Prosty Google znajdzie dla ciebie mnóstwo artykułów.
DeadMG,
5
Dwie małe, ale ważne korekty IMHO: limit 40 godzin tygodniowo jest przybliżoną wartością średnią, a reguła obowiązuje tylko przez dłuższy czas. Zespół może poświęcić dodatkowe godziny przed ważnym terminem, a następnie wyzdrowieć (może nawet wziąć kilka dni wolnego). Ponadto limit jest różny dla różnych osób i z czasem - niektórzy mogą pracować 43 godziny tygodniowo bez problemów, inni tylko 35, a jeden jest bardziej produktywny w niektórych tygodniach niż inni. Jednak poświęcenie znacznej liczby godzin nadliczbowych na więcej niż kilka tygodni z rzędu rzeczywiście spowoduje poważne problemy.
Péter Török
13

Pracuję w firmie, która uzyska 11 punktów w teście Joela - przynajmniej na papierze.

Ten test ma jedynie niewielkie znaczenie dla firm produkujących oprogramowanie. Nie rozumiem szumu na ten temat. Możesz zdobyć 12 punktów i nadal mieć 100% programistów bzdur. Ludzie są ważniejsi niż narzędzia.

Jednak zastrzeżone narzędzia wymieniają takie rzeczy, jak niejawne rzutowania i rozmiar literału łańcuchowego. Niejawne obsady również znajdują się na czarnej liście w ich książce stylów. Standardową praktyką jest zmuszanie ludzi do zamykania każdego ostrzeżenia. Pamiętaj, że nie wyklucza to ostrzeżeń, które są w większości fałszywie dodatnie, to nie jest problem.

Jest to największy problem ze wszystkimi analizatorami statycznymi: zbyt wiele wyników fałszywie dodatnich. Tylko sposób obsłużyć to jest dowiedzieć się szczegółowo , dlaczego narzędzie zostało ustawione dać ostrzeżenie dla pewnej kwestii. Tylko wtedy możesz przyjąć kwalifikowane założenia, czy ostrzeżenie jest fałszywe, czy nie.

W przypadku konkretnej obsady typów niejawnych jest to spowodowane kilkoma bardzo powszechnymi, subtelnymi i niebezpiecznymi błędami w języku C, spowodowanymi dwiema (kretyńskimi) niejawnymi zasadami promocji typu w C. Są one formalnie znane jako reguły promocji liczb całkowitych i zwykłe konwersje arytmetyczne . Myślę, że mniej niż jeden na dziesięciu wszystkich profesjonalnych programistów C może wyjaśnić, co robią te dwie reguły, a czego nie. A jednak reguły te są niezwykle podstawowe i stosowane tysiące razy między wierszami w każdym normalnym programie C.

Norma MISRA-C poświęciła cały rozdział objaśniając te niebezpieczne ukryte reguły konwersji, a następnie dodała wiele dość skomplikowanych reguł dotyczących unikania błędów spowodowanych przez ukrytą konwersję. Miało to dość duży wpływ na wszystkie analizatory statyczne na rynku.

Poleciłbym każdemu programistowi C, aby przeczytał ten rozdział MISRA-C, a przynajmniej Google, dwie zasady promocji, o których wspomniałem i przeczytał o nich jak najwięcej. Możesz zignorować analizator statyczny tylko wtedy, gdy wiesz wszystko na temat tych reguł.

Nie sądzę, żeby tę firmę można było uratować. Chciałbym jednak wiedzieć, czy istnieje lepszy, najlepiej działający sposób korzystania z narzędzi „pro”, czy też powinienem po prostu całkowicie ich unikać, na wypadek, gdyby to ja podejmowałem decyzję w przyszłości.

Rozwiązanie, które nie zakłada, że ​​wszyscy programiści są geniuszami, którzy nie mogą się mylić. Ponieważ cóż, jeśli tak, to nie ma potrzeby używania narzędzi w pierwszej kolejności.

Nie ma łatwego sposobu na obejście tego. Prawdziwym problemem nie jest tak naprawdę narzędzie, ale niejasny język C. Na pierwszy rzut oka może się to wydawać łatwym językiem, ale między wierszami dzieje się wiele nielogicznych i dziwnych mechanizmów. Istnieją również setki przypadków nieokreślonego / nieokreślonego / nieokreślonego zachowania w języku. Większość z nich musisz się nauczyć i unikać.

Musisz więc zostać doświadczonym programistą C, który rozumie wszystkie te niejasne ostrzeżenia, lub musisz być w zespole z co najmniej jedną taką osobą. Firmy, które zatrudniają tylko grupę młodszych programistów bez weteranów w zespole, nie powinny korzystać z tych narzędzi ani nie powinny pracować z programowaniem o wysokiej integralności.


źródło
Od początku przystąpiłem do testu ze szczyptą soli, ale nie jest to narzędzie do testowania programistów, ale narzędzie do testowania pracodawców. Wydaje mi się, że można zaliczyć trafnych współpracowników jako „najlepsze narzędzia, jakie można zapłacić za pieniądze”. Przyjmuję twoją odpowiedź, aby wyrzucić narzędzia SA i lepiej zatrudnić i / lub trenować. Pierwszy punkt wydaje się być wspólnym mianownikiem.
@qpr Nie testuje też pracodawcy, tylko gotowość pracodawcy do wydania pieniędzy na rozwój oprogramowania. Rzeczy takie jak procedura rekrutacji, cele korporacyjne, znajomość rynku itp. Nie są wspomniane. Myślę, że większość firm „bańki informatycznej” uzyskałaby w tym teście 12 punktów, a kierownictwo nie wie nawet, które produkty są opracowywane lub czy istnieje dla nich jakikolwiek rynek.
4

Nie jest jasne, czy pytasz, jak rozwiązać problem, czy w jaki sposób możesz go uniknąć. Zakładam to drugie.

Wygląda na to, że polegasz na analizie statycznej, która jest podstawowym sposobem wykrywania i unikania błędów. Być może lepiej byłoby skupić się bardziej na testach jednostkowych i narzędziach dynamicznych ... takich jak kontrolery pamięci.

Oparcie się na narzędziu, które generuje wiele wyników fałszywie dodatnich, jest złe, szczególnie jeśli nie można stłumić tych wyników fałszywie dodatnich. Zachęca zmęczonych / przepracowanych (lub leniwych) programistów do dokonywania „poprawek”, aby ostrzeżenia zniknęły. Jeśli nie możesz selektywnie tłumić fałszywych alarmów (np. Z komentarzami) lub dostosować zestaw reguł, potrzebujesz lepszego narzędzia. A przynajmniej powinieneś używać go oszczędnie.

Wygląda na to, że masz problem z tym, że ludzie są nieostrożni i / lub popełniają błędy z powodu przepracowania. Być może powinieneś poświęcić więcej czasu / wysiłku na przeglądy kodu. To bezpośrednio odnosi się do twojej obserwacji, że programiści nie są geniuszami.

Wreszcie brzmi to tak, jakbyś cierpiał w nierealistycznych terminach, wymaganiach związanych z zasobami ludzkimi i / lub zmianami. Jest to problem zarządzania i należy się nim zająć na tym poziomie ... w przeciwnym razie istnieje znacznie podwyższone ryzyko niepowodzenia projektu oraz długoterminowe pogorszenie wydajności i morale pracowników.

Stephen C.
źródło
3

Oprócz doskonałej odpowiedzi użytkownika user29079, chciałbym dodać jeszcze jedną wadę języka C, która zwiększa problem. Nie wiedziałem o tym niedoborze, dopóki nie przeszedłem na Javę.

Ostrzeżenie ma na celu zwrócenie uwagi autora i przyszłych czytelników kodu na fakt, że dzieje się coś podejrzanego. To jako koncepcja jest w porządku: im więcej ostrzeżeń włączysz, tym więcej podejrzanych rzeczy odkryjesz.

To, co jest całkowicie błędne , to przekonanie, że każdy drobiazg musi zostać naprawiony za wszelką cenę poprzez zmianę kodu . To właśnie spowodowało problem, który opisuje OP: nieudane próby pośpiesznego usunięcia ostrzeżeń przez zmianę kodu, który działa dobrze.

Jednocześnie nie chcemy, aby nasz kod wyrzucał setki ostrzeżeń za każdym razem, gdy się kompilujemy, ponieważ wkrótce ostrzeżenia stają się bez znaczenia i nikt nie zwraca już uwagi na nowe ostrzeżenia.

Tak więc wydaje się, że chodzi o sprzeczne cele; sprzeczność.

Bardzo dobrym rozwiązaniem tego pozornie niemożliwego do rozwiązania problemu jest możliwość selektywnego zniesienia pewnego ostrzeżenia na podstawie stwierdzenia po oświadczeniu, abyśmy mogli je ukryć dokładnie tam, gdzie chcemy wskazać, że naprawdę wiemy, co robimy, bez konieczność zmiany dowolnego kodu.

Java ma dobre rozwiązanie tego problemu z @SuppressWarnings( "" )adnotacją. Jeśli wykonujesz, powiedzmy, tak zwaną niesprawdzoną konwersję w Javie, kompilator wydaje ostrzeżenie, aby zwrócić na to uwagę, badasz to, stwierdzasz, że jest to jeszcze jeden z tych przypadków, w których wiesz, co robisz, dlatego poprzedzasz złoczyńcze stwierdzenie @SuppressWarnings( "unchecked" )adnotacją, która dotyczy tylko na oświadczenie, które następuje bezpośrednio po nim, i kontynuujesz swoje życie.

Tak więc ostrzeżenie znika, kod pozostaje niezmieniony, a adnotacja tłumienia stoi tam, oznaczona kolorem zielonym przez podświetlanie składni, aby udokumentować fakt, że ma miejsce niepewna konwersja, ale autor obiecuje, że jest dobry. (*) Wszyscy są szczęśliwi.

W Javie możesz nawet poprzedzać poszczególne parametry funkcjami za pomocą @SuppressWarnings() , aby wyłączyć określone ostrzeżenie, które może zostać wydane tylko dla tego konkretnego parametru.

Jednak, o ile mi wiadomo, C nigdy nie wspierał żadnego standardowego mechanizmu selektywnego tłumienia ostrzeżeń na wyciągach, a niektóre kompilatory, które implementowały własne zastrzeżone mechanizmy, zrobiły to w sprytny sposób, na przykład #pragma warning (nnn:N)dyrektywy Microsoft C. Problem z tymi dyrektywami jest to, że potrzebujesz dwóch wierszy dyrektyw, aby oba zignorować ostrzeżenie dla pojedynczej instrukcji i pozostawić to ostrzeżenie włączone dla kolejnych instrukcji. Dlatego programiści C raczej nie zauważą nawyku tłumienia ostrzeżenia na podstawie pojedynczych instrukcji, nawet jeśli wiedzą, że to konkretne ostrzeżenie na tej konkretnej instrukcji jest w porządku.


(*) ktoś może argumentować, że jeśli na to zezwolisz, to każdy programista w domu będzie tłumił ostrzeżenia bez zastanowienia; odpowiedź na to jest taka, że ​​możesz zrobić wszystko, aby pomóc programistom lepiej wykonywać swoją pracę, ale nic nie możesz zrobić, jeśli aktywnie zdecydują się cię sabotować.

Mike Nakis
źródło
Innymi słowy, chociaż zmiana źródła w celu usunięcia każdego ostatniego ostrzeżenia jest kluczem do dobrej praktyki, zmiana kompilowalnego kodu nie jest, ponieważ eliminuje prosty kod, który jest po prostu poprawny bez powodu. Dobre rozróżnienie.
Nathan Tuggy,
2

Powiedziałbym (nie znając szczegółów), że Twoja firma popełniła poważniejsze błędy, a to tylko symptom: nie udało się właściwie określić domeny produkowanego oprogramowania, właściwie zarządzać zespołem i określić rozsądnych celów.

Jeśli oprogramowanie, które tworzy zespół, jest czymś krytycznym, od którego zależy ludzkie życie, narzędzia analizy statycznej są ważne i przydatne. Ponieważ „koszt” błędu, mierzony w pieniądzach (ignorując jego cyniczność), jest wysoki, do wykonania tego zadania potrzebne są specjalne narzędzia. Istnieją wytyczne zarówno dla C, jak i C ++ dotyczące bezpiecznego korzystania z funkcji językowych (przeczytaj, czego unikać i jak daleko się posunąć, unikając tego).
Jednak w takiej sytuacji zatrudnianie pracowników w niedzielę jest bardzo złym pomysłem, a ponadto z kontekstu, który podałeś, ekstrapoluję, że niechlujna praca nie jest rzadka. Jeśli tak jest, problem jest bardzo, bardzoduży, a twoje kierownictwo próbuje to rozwiązać, używając „lepszych” narzędzi. Niestety, nie tak to działa. Jeśli nawet jestem blisko poprawienia, posunę się aż do zasugerowania, abyś zaczął szukać innej pracy. Źle wykonane oprogramowanie o znaczeniu krytycznym może cię prześladować i zrujnować Twoją reputację zawodową, nie wspominając już o perspektywach procesu.

Z drugiej strony, jeśli Twój zespół pisze coś o wiele mniej krytycznego, narzędzia „analizy statycznej” o wysokim współczynniku wyników fałszywie dodatnich tylko spowolnią cię i, jak zauważyłeś, ludzie zwykle reagują na to poprzez: znajdowanie lokalnego maksimum skuteczności, w tym przypadku po prostu oszukiwanie ostrzeżeń, zamiast próbować ustalić przyczynę. Tak więc w twojej sytuacji użycie tych narzędzi może faktycznie pogorszyć jakość kodu źródłowego i ogólnie należy ich unikać.

Jeśli jesteś trzeba zarządzać zespołem oprogramowania, który jest pisanie trochę C lub C ++ kod, powiedziałbym najpierw ustalić, jakie są główne cele projektu. Jeśli pisanie kodu wolnego od błędów ma ogromne znaczenie (np. Nowa super niesamowita aplikacja społecznościowa na iOS i Androida nie pasuje do tego), skorzystaj z analizy statycznej, może nawet posunąć się do formalnej specyfikacji i formalnej weryfikacji. Ale jeśli tak jest, wybór dobrych programistów i zapewnienie im pracy w rozsądnym środowisku z odpowiednim obciążeniem i odpowiednim 40-godzinnym tygodniem jest o wiele ważniejsze.

Ludzie nie mogą pracować odpowiedzialnie, jeśli są traktowani jak niewolnicy (a właśnie taki jest ktoś zajmujący moje wakacje), a dobrzy programiści po prostu odmawiają robienia tego regularnie, chyba że nie wiedzą nic lepszego (a jeśli są dobrzy, szanse są robią).

Podsumowując: Określ swoje cele, a następnie określ narzędzia i proces, którego używasz, nie pozwól dostępnym narzędziom zdefiniować proces (ergo cele), ponieważ (złe) kierownictwo może chcieć cię zmusić.

K.Steff
źródło
1

Jak stwierdzono w odpowiedzi k.steff, narzędzia analizy statycznej dla „C” są przydatne, jeśli budujesz oprogramowanie w krytycznej sytuacji (oprogramowanie samolotu) i należy ich używać od pierwszego dnia (nie po miesiącach programowania, gdy wystąpi nieodtwarzalny błąd ).

Korzystanie z tego rodzaju narzędzi na późnym etapie procesu programowania jest zwykle oznaką złych wyborów projektowych na wczesnym etapie procesu.

W niekrytycznym oprogramowaniu tego rodzaju narzędzia są przydatne do: -
zapewnienia bezpieczeństwa, sprawienia, by były użyteczne (zrobiliśmy coś, wydaliśmy dużo pieniędzy na naprawę oprogramowania). Daje im działania, które łatwo wykonać w raportach Powerpoint).
-Utrzymaj zajęcie „toksycznych” programistów. Pozwól im skonfigurować narzędzie i przeanalizować wyniki narzędzia, abyś miał czas na naprawienie ich paskudnych błędów.
-wymagać reguł kodowania. W takim przypadku należy go używać od pierwszego dnia. Ale dobrym narzędziem do sprawdzania kodu może być lepszy wybór.

Dlatego uważam, że musisz unikać tego rodzaju drogich, czasochłonnych narzędzi lub używać ich, aby „zatruć” ludzi.

FrenchKiss Dev
źródło
1

Pracuję w firmie, która uzyska 11 punktów w teście Joela - przynajmniej na papierze.

Walidacja przez test Joela nie jest miarą dobrych praktyk; Unieważnienie przez test Joela jest jednak miarą złych / brakujących praktyk. Innymi słowy, można to uznać za konieczne, ale niewystarczające.

Teraz większość moich rówieśników jest zadowolona, ​​jeśli mogą wrócić do domu o 18:00 - w niedzielę.

Wygląda na to, że masz problem z zarządzaniem. Systematyczne nadgodziny nie stanowią rozwiązania problemu; jeśli już, to jest rozwiązanie, dzięki któremu wszystko wygląda tak , jakby działało, i narasta dług techniczny.

Nie sądzę, żeby tę firmę można było uratować. Chciałbym jednak wiedzieć, czy istnieje lepszy, najlepiej działający sposób korzystania z narzędzi „pro”, czy też powinienem po prostu całkowicie ich unikać, na wypadek, gdyby to ja podejmowałem decyzję w przyszłości.

Tak, istnieje sposób na rozsądne użycie statycznej analizy kodu.

Mogą i zazwyczaj zapewniają dużą wartość. Trzeba tylko pamiętać, że (podobnie jak ostrzeżenia kompilatora) narzędzie do analizy statycznej może (co najwyżej) dawać wskazówki dotyczące czegoś, co się nie udaje - nie raportów o błędach i żadnej pewności.

Wygląda na to, że decydenci mylą flagi analizy statycznej z wadami aplikacji.

Niejawne obsady również znajdują się na czarnej liście w ich książce stylów.

Brzmi to jak problem kompetencji menedżerskich, a nie problem analizy statycznej.

Wynik to:

Ludzie dodają typy rzutów do każdej wartości i każdego argumentu, ukrywając w tym procesie prawdziwe niedopasowania typów.

Ludzie wprowadzają się przez jeden błąd lub używają innej problematycznej funkcji języka (strlen zamiast sizeof, strncpy zamiast strcpy itp.)

Ostrzeżenia zostały wyciszone.

Raporty o błędach zaczynają się pojawiać.

Wszystkie te są sposoby, aby raporty okresowe wyglądały dobrze, a nie sposoby rozwiązywania problemów w kodzie (wygląda na to, że masz problem z kompetencjami do zarządzania).

utnapistim
źródło