Dlaczego warto chcieć wyłączyć ostrzeżenia kompilatora?

26

Ta odpowiedź i dodane do niej komentarze pokazują sposób na wyłączenie kilku ostrzeżeń kompilatora za pomocą #pragmadyrektyw.

Dlaczego miałby to robić? Zazwyczaj ostrzeżenia są z jakiegoś powodu i zawsze uważałem, że są to dobre powody. Czy istnieje „ważny przypadek”, w którym należy wyłączyć ostrzeżenia? W tej chwili nie mogę wymyślić żadnego, ale może to tylko ja.

takrl
źródło
4
Nie jestem pewien, dlaczego ktoś oznaczył to jako zamknięcie. Wydaje mi się niezwykle rozsądnym pytaniem. +1
@Alastair Pitts: Zaproponowałem migrację do programistów. Później zrozumiałem swój błąd.
Tugrul Ates
3
Komunikaty ostrzegawcze istnieją z jakiegoś powodu, ale istnieje też powód, dla którego nie są komunikatami o błędach.
Solomon Slow
2
@jameslarge Twój komentarz ładnie podsumowuje sytuację. Ostrzeżenie to kompilator informujący, że sytuacja jest prawdopodobnie błędna , co sugeruje prawdopodobnie słuszność . Jeśli byłoby to zdecydowanie złe , byłby to błąd. Ponieważ niektóre ostrzeżenia mogą być fałszywie pozytywne, zawsze powinien istnieć sposób na napisanie kodu, który wyeliminuje ostrzeżenie. Niestety, czasem najbardziej pragmatycznym sposobem jest pragma; stąd nazwa.
Eric Lippert,
Nie wyłącza się, ukrywa. Problem nadal będzie istniał tylko dlatego, że nie zobaczysz go takim, jaki jest
Sisir

Odpowiedzi:

11

Miałem tylko jedną sytuację, w której wyłączyłem ostrzeżenie. Rozważam błędy ostrzeżeń, więc normalnie nie wypuszczałbym ostrzeżeń. Jednak podczas opracowywania interfejsu API u klientów napotkałem problem polegający na tym, że metoda, która była potrzebna w fazie migracji przez jedną aplikację i z której nie powinna korzystać żadna inna, musiała zostać zawarta w bibliotece.

Najlepszym sposobem, w jaki mogłem powiedzieć wszystkim użytkownikom interfejsu API, że nie powinni wywoływać tej metody, było oznaczenie jej jako przestarzałej. Oznaczało to jednak, że jeden poprawny przypadek użycia został oznaczony jako ostrzeżenie kompilacyjne.

Eric Lippert napisał kilka postów na temat ostrzeżeń, w których znajdziesz informacje o tym, jak zespół kompilatora myśli o ostrzeżeniach.

Wewnętrzne pola typów wewnętrznych

Niewykorzystane przy użyciu dyrektyw nie są oznaczone ostrzeżeniami

Rune FS
źródło
10

Oto kilka ostrzeżeń, w których dokumentacja podaje powody, dla których warto je wyłączyć:

Inne przykłady obejmują ostrzeżenia o stosowaniu zamortyzowanych metod, jeśli wiesz, że nadal chcesz korzystać ze starej metody lub masz prywatnych członków, którzy nigdy nie są czytani lokalnie, ale zamiast tego mają refleksję.

Z mojego doświadczenia wynika, że ​​C # ma mniejszą potrzebę wyłączania ostrzeżeń niż inne języki, takie jak C ++. Wynika to głównie z tego, że, jak mówi Eric Lippert na swoim blogu , „próbują zastrzec ostrzeżenia tylko dla tych sytuacji, w których możemy z całą pewnością stwierdzić, że kod jest uszkodzony, wprowadzający w błąd lub bezużyteczny”.

ICR
źródło
3
Miły. Myślę, że pierwszy jest najbardziej przejrzysty, ponieważ zawiera bardzo konkretny przypadek i uzasadnienie (na przykład trzeci pokazuje fragment kodu, który nigdy nie przejdzie przeglądu w moim zespole). To pytanie dotyczy przestarzałych / osłabionych ostrzeżeń. Zasadniczo są one nadal potrzebne w starszym kodzie, ale chcesz zniechęcić do używania nowego kodu. W starszym kodzie należy wyłączyć ostrzeżenia.
Greg Jackson
Zrobiłem dużo programowania makr w programie Excel i musiałem wyłączyć ostrzeżenia z różnych powodów, takich jak automatyczne zapisywanie, automatyczne wyjście, powiadomienia itp. Oczywiście możesz nie wiedzieć o tych ostrzeżeniach ...
Dave Mess
@ICR Nie pamiętam w ogóle wyłączania ostrzeżeń kompilatora w Javie. Wszystko, co robię, to unikam stosowania przestarzałych metod.
Mahmoud Hossam,
@Mahmoud Bardzo często zdarza mi się tłumić „niesprawdzone” ostrzeżenia, gdy robię coś nawet zdalnie złożonego z lekami generycznymi. Ale prawdopodobnie niesprawiedliwe jest dodawanie Javy za pomocą C ++ w absurdalnych ostrzeżeniach - zredagowałem moją odpowiedź.
ICR
@ICR Java wymusza stosowanie rodzajów ogólnych w celu zapewnienia bezpieczeństwa typu w kolekcjach, podczas gdy niektórzy postrzegają to jako ograniczenie, myślę o tym jako o funkcji, sprawia, że ​​pisanie kodu jest trochę bolesne, ale ratuje życie i tak, wyjście kompilatora C ++ jest nieco przerażające, jeśli chodzi o STL lub cokolwiek z szablonami.
Mahmoud Hossam,
8

Przykład w C, z którym regularnie spotykam się z wariantami:

int doSomething(int argument1)
{
#ifdef HARDWARE_TYPE_A
    performAction(argument1);
#else
    displayNotSupportedMessage();
#endif
}

Argument jest istotny tylko na niektórych platformach, ale na tych, na których nie ma to znaczenia, mój kompilator będzie narzekał, a ponieważ mam ostrzeżenia skonwertowane na błędy, uniemożliwi to jego budowę.

Konwersja ostrzeżeń na błędy wymaga włazu awaryjnego dla „nie tego, wiem lepiej niż kompilator w tym przypadku”.

pjc50
źródło
6

Wiele niezbędnych bibliotek Java nigdy nie zostało zaktualizowanych w celu wyeliminowania potrzeby tworzenia niebezpiecznych typecastów. Tłumienie tych ostrzeżeń jest konieczne, aby inne ważniejsze ostrzeżenia zostały zauważone i poprawione.

Kevin Cline
źródło
5

Wykonuję pracę osadzoną i wydaje mi się, że pamiętam jakiś czas, kiedy wyłączyłem ostrzeżenia, ponieważ robiłem coś, co wydawało się bezużyteczne dla kompilatora, ale które faktycznie miało rzeczywiste efekty w sprzęcie.

Jedyny inny czas to praca z podstawami kodu z odmiennymi pomysłami na pewne struktury danych (np. Jak reprezentować tablice bajtów - znak lub znak bez znaku?). W takich przypadkach mogę wyłączyć ostrzeżenia, ponieważ alternatywą jest spędzanie dni na przeglądaniu kodu i modyfikowaniu jednej części lub wprowadzaniu setek rzutów.

Michael Kohne
źródło
3

Istnieje wiele powodów, aby selektywnie wyłączać ostrzeżenia kompilatora, nawet w przypadku projektów, które dążą do najlepszych praktyk.

  • Różne kompilatory (lub różne wersje tych samych kompilatorów) :
    Kompilatory przetwarzają ostrzeżenia w subtelny sposób na różne sposoby. Przekazywanie fałszywie dodatnich ostrzeżeń, które nie wpływają na inne kompilatory. W takim przypadku sensowne może być wyłączenie ostrzeżenia dla tych kompilatorów, zamiast edytowania poprawnego kodu w celu wyciszenia fałszywie dodatniego ostrzeżenia, które wpływa tylko na niektóre kompilatory, szczególnie dla starszych kompilatorów, które ostatecznie nie będą obsługiwane.
  • Z wygenerowanym kodem:
    Niektóre ostrzeżenia związane z higieną kodu (martwy kod, zduplikowana treść instrukcji warunkowych, porównania przekraczające limity typów) można bezpiecznie zignorować, ponieważ są nieszkodliwe, a kompilator je zoptymalizuje.
    Generowanie kodu, który nie wywołuje tych nieszkodliwych ostrzeżeń, jest oczywiście również opcją, ale może być większym kłopotem niż wartością.
  • Ostrzeżenia dotyczące kodu zewnętrznego:
    Być może używasz dobrze znanej implementacji sumy kontrolnej qsort lub md5, która jest zawarta w twoim projekcie. Kod jest używany w wielu projektach i wiadomo, że działa dobrze, ale mogą wystąpić pewne wybredne ostrzeżenia, które zwykle poprawiasz dla własnego kodu.
    Jednak w przypadku kodu zewnętrznego wyłączenie ostrzeżenia może być mniej kłopotliwe (zakładając, że jest to zdecydowanie nieszkodliwe).
  • Ostrzeżenia wywoływane przez nagłówki systemu:
    Mimo że na przykład obsługa GCC / Clang -isystem, różnice w nagłówkach systemu powodują ostrzeżenia, które można zignorować (być może funkcja ma podpisaną wartość zwrotną w jednym systemie, ale nie w innym), wywołując -Wsign-compareostrzeżenia.
    Innym przypadkiem mogą być makra zdefiniowane w nagłówkach systemowych, możesz skopiować i wkleić makra do własnego kodu, aby je zmodyfikować, ale wszystko uważało, że lepiej nie martwić się o utrzymanie makr z bibliotek stron trzecich ... więc lepiej po prostu wyciszyć ostrzeżenie (być może makro nie trafia w obsadę powodując -Wsign-conversionnp.).
  • Nieużywane ostrzeżenia w kodzie pośredniczącym:
    Możesz ostrzegać przed nieużywanymi parametrami, jednak przy usuwaniu całej biblioteki w jednym pliku zawierającym tylko funkcje pośredniczące - nie jest pomocne wymuszanie (void)arg1; (void)arg2; (void)arg3; ...w treści każdej funkcji pośredniczącej.
    Lepiej po prostu pomiń -Wunused-parameterw tym przypadku.

Należy zauważyć, że we wszystkich tych przykładach jego zakładał wyłączenie ostrzeżenia nie zamierza ukrywać rzeczywiste błędy, np: -Wredundant-decls, -Wunused-parameter, -Wdouble-promotion, być może -Wpedantic... i że wiesz, co robisz!

ideasman42
źródło
2

Prawidłowe czy nie, czasami robi się to w celu ominięcia dyrektywy „traktuj ostrzeżenia jak błędy” na serwerze kompilacji.

Poza tym nie mogę wymyślić żadnego z nich. Wyłączone ostrzeżenia są zwykle oznaką „brzydkiego haxa” ...

David Božjak
źródło
2

Ostatnim razem, kiedy wyłączaliśmy niektóre ostrzeżenia, było to spowodowane tym, że stażysta zostawił nam zły kod. Mam go o wiele lepiej, a wyraźne granice konwersji zastępują przypadkową reprezentację danych.

W międzyczasie musieliśmy go skompilować i chcieliśmy włączyć opcję „ostrzeżenia są błędami”, dlatego niektóre ostrzeżenia zostały pominięte.

David Thornley
źródło
2

Obecnie jedynym ostrzeżeniem, które zignorowałem, jest

  warning C4290: C++ exception specification ignored except to indicate a function is not __declspec(nothrow)  

Ponieważ Microsoft nie implementuje specyfikacji C ++ (dokumentacja mówi nawet, że nie!) I zezwala funkcjom na deklarowanie określonych rzutów, a wszystkie funkcje mogą rzucać tylko throw () lub throw (...), tzn. Nic lub wszystko.

Z HelpViewer 1.1:

 A function is declared using exception specification, which Visual C++ accepts but does not implement. Code with exception specifications that are ignored during compilation may need to be recompiled and linked to be reused in future versions supporting exception specifications. 
Casey
źródło