W językach C i C ++ bardzo łatwo jest napisać następujący kod z poważnym błędem.
char responseChar = getchar();
int confirmExit = 'y' == tolower(responseChar);
if (confirmExit = 1)
{
exit(0);
}
Błąd polega na tym, że instrukcja if powinna była:
if (confirmExit == 1)
Po zakodowaniu wyjdzie za każdym razem, ponieważ confirmExit
nastąpi przypisanie zmiennej, a następnie confirmExit
zostanie użyte jako wynik wyrażenia.
Czy istnieją dobre sposoby, aby zapobiec tego rodzaju błędom?
c++
coding-standards
DeveloperDon
źródło
źródło
if (confirmExit)
.a = b
luba == b
wewnątrz.Odpowiedzi:
Najlepszą techniką jest zwiększenie poziomu ostrzegania twojego kompilatora. Ostrzeże Cię wtedy o potencjalnym przypisaniu w warunkowym warunkowym.
Upewnij się, że skompilowałeś swój kod z zerowymi ostrzeżeniami (co i tak powinieneś robić). Jeśli chcesz być pedantyczny, ustaw kompilator tak, aby traktował ostrzeżenia jako błędy.
Używanie warunkowych Yoda (umieszczanie stałej po lewej stronie) było kolejną techniką, która była popularna około dziesięć lat temu. Ale sprawiają, że kod jest trudniejszy do odczytania (a tym samym zachowuje się z powodu nienaturalnego sposobu, w jaki czytają (chyba, że jesteś Yodą)) i nie zapewniają większych korzyści niż zwiększenie poziomu ostrzeżenia (co ma również dodatkowe zalety w postaci większej liczby ostrzeżeń).
Ostrzeżenia są naprawdę logicznymi błędami w kodzie i powinny zostać poprawione.
źródło
if (0 == ret)
horroru.a == b
!!0==a && 0==b || 1==a && 1==b || 2==a && 2==b || ...
(powtórz dla wszystkich możliwych wartości). Nie zapomnij o obowiązkowym...|| 22==a && 22==b || 23==a && 24==b || 25==a && 25==b ||
... błędzie, bo programiści nie będą się dobrze bawić.Zawsze możesz zrobić coś radykalnego, np. Przetestować oprogramowanie. Nie mam nawet na myśli automatycznych testów jednostkowych, tylko testy, które każdy doświadczony programista przyzwyczaja, uruchamiając swój nowy kod dwa razy, raz potwierdzając wyjście, a raz nie. Dlatego większość programistów uważa to za problem.
źródło
rc=MethodThatRarelyFails(); if(rc = SUCCESS){
więcej niż jeden raz, szczególnie jeśli metoda zawiedzie tylko w trudnych warunkach.Tradycyjnym sposobem zapobiegania niepoprawnemu użyciu przypisań w wyrażeniu jest umieszczenie stałej po lewej stronie i zmiennej po prawej stronie.
Kompilator zgłosi błąd dotyczący nielegalnego przypisania do stałej podobnej do poniższej.
Zmieniony warunek byłby:
Jak pokazują poniższe komentarze, wielu uważa to za nieodpowiednią metodę.
źródło
Zgadzam się ze wszystkimi, którzy mówią „ostrzeżenia kompilatora”, ale chcę dodać inną technikę: recenzje kodu. Jeśli masz zasady sprawdzania całego kodu, który zostanie zatwierdzony, najlepiej przed jego zatwierdzeniem, prawdopodobnie podczas przechwytywania tego rodzaju problem zostanie przechwycony.
źródło
Po pierwsze, podnoszenie poziomów ostrzegawczych nigdy nie boli.
Jeśli nie chcesz, aby warunek testował wynik przypisania w samej instrukcji if, to pracując z wieloma programistami C i C ++ przez lata i nigdy nie słysząc, że porównywanie stałej jako pierwszej
if(1 == val)
było złą rzeczą, mógł wypróbować ten konstrukt.Jeśli lider projektu wyrazi na to zgodę, nie martw się o to, co myślą inni ludzie. Prawdziwym dowodem jest to, czy ty lub ktoś inny możesz zrozumieć swój kod za miesiące i lata.
Jeśli jednak chciałbyś przetestować wynik przypisania, użycie wyższych ostrzeżeń mogłoby [prawdopodobnie] uchwycić przypisanie do stałej.
źródło
if ( auto myPtr = dynamic_cast<some_ptr>(testPtr) ) {
to, że unika się utrzymywania bezużytecznegonullptr
zakresu, jeśli rzutowanie się nie powiedzie - co jest prawdopodobnie przyczyną, dla której C ++ ma ograniczoną możliwość przypisywania w ramach warunku. Co do reszty, tak, definicja powinna mieć swoją własną linię, powiedziałbym - znacznie łatwiej zobaczyć na pierwszy rzut oka i mniej podatna na różne wpadki.Spóźniamy się na imprezę jak zawsze, ale kluczem jest tu analiza kodu statycznego
Większość IDE zapewnia teraz SCA poza kontrolą składniową kompilatora, a inne narzędzia są dostępne, w tym te, które implementują wytyczne MISRA (*) i / lub CERT-C.
Deklaracja: Należę do grupy roboczej MISRA C, ale zamieszczam się osobiście. Jestem także niezależny od jakiegokolwiek dostawcy narzędzi
źródło
Po prostu użyj przypisania lewej ręki, ostrzeżenia kompilatora mogą pomóc, ale musisz upewnić się, że osiągniesz odpowiedni poziom, w przeciwnym razie albo zostaniesz zalany bezsensownymi ostrzeżeniami, albo nie powiesz tym, których chcesz zobaczyć.
źródło