Przyjaciel mojej rodziny poprosił mnie o trochę pomocy, gdy uczy się programować (w języku C). Gdy rozmawialiśmy, wyraził frustrację z powodu trudności w zrozumieniu komunikatów o błędach, które wysyła mu jego kompilator (GCC), gdy popełnia błędy. Nie rozumie wszystkich użytych terminów, a czasem ich kombinacja jest poza jego zrozumieniem. Pytał mnie: „Dlaczego dokumentacja kompilatora nie zawiera dłuższych wyjaśnień komunikatów o błędach?” - i nie miałem dla niego dobrej odpowiedzi.
Ja sam - jako bardziej doświadczony programista - bardzo rzadko jestem w takiej sytuacji, ale zdarzają się te rzadkie zdarzenia - jakiś egzotyczny komunikat o błędzie, z którym się wcześniej nie spotkałem. Udaje mi się znaleźć komunikat o błędzie w wyszukiwarce, ale najwyraźniej nie zawsze to dla niego działa - zwłaszcza, że napotkane błędy są częstsze i występują w wielu różnych przypadkach, z którymi ma problemy związane z jego posiadać.
Jak więc początkujący programista powinien podjąć wyzwanie zrozumienia komunikatów o błędach kompilatora? W szczególności z kombinacją C i GCC?
źródło
Yes.
lub wNo.
zależności od tego, czy kod został skompilowany, czy nie. Natychmiast usuwa frustrację z powodu niezrozumienia długich i bezcelowych wiadomości!Odpowiedzi:
Kilka przydatnych technik:
-Wall
i-Werror
. Może to wydawać się sprzeczne z intuicją, gdy masz problemy z odszyfrowaniem komunikatów o błędach, aby utworzyć jeszcze więcej komunikatów o błędach, ale ostrzeżenia są zwykle łatwiejsze do zrozumienia i bliższe rzeczywistemu źródłu problemu, a ich zignorowanie może prowadzić do błędów, które są trudne do zrozumienia .źródło
Twój przyjaciel nie potrzebuje słownika. Glosariusz mu nie pomoże. Potrzebuje lepszej intuicji, co zrobić, gdy wystąpią błędy kompilatora.
Błędy kompilatora C nie są tak intuicyjne jak, powiedzmy, błędy kompilatora C #, z wielu powodów głównie związane z „bliską metalem” naturą C. Rozwiązywanie błędów kompilatora w C nie jest ćwiczeniem polegającym na dopasowaniu wzorca, ponieważ błąd Odbieranie może nie mieć nic wspólnego z rzeczywistym problemem. W przeciwieństwie do C # lub Java, gdzie komunikat o błędzie zwykle odwzorowuje dokładną lokalizację kodu i problem, błędy w C mogą być liczne i dalekie.
Przykładem tego jest „oczekiwany średnik” lub dowolna liczba błędów składniowych, które wskazują, że parser zawiesił się na czymś (niekoniecznie średnik). Lub coś w rodzaju „nieoczekiwanej deklaracji przekazania”, błąd, który, gdy go widzę, niezmiennie oznacza, że źle zapisałem wielkie litery w jednym z moich plików .h, ale który nie wskazuje na plik .h jako źródło problemu.
Strategią twojego przyjaciela nie powinno być dopasowanie wzoru do listy błędów i rozwiązań; powinno być wystarczająco dobrze rozumieć składnię i specyfikację języka C, aby dowiedzieć się, na czym polega rzeczywisty problem.
źródło
Istotną techniką, o której warto wspomnieć, jest użycie drugiego kompilatora. Na przykład Clang zainwestował w lepsze komunikaty o błędach, ale każdy alternatywny sposób sformułowania błędu może być pouczający.
Jest to szczególnie ważne w przypadku najbardziej skomplikowanych rodzajów błędów. Na przykład, gdy pomieszasz dwie podobne konstrukcje (co nie jest niczym niezwykłym dla początkujących), kompilatory zwykle mają problem z wygenerowaniem odpowiedniego komunikatu o błędzie. Może to powodować zamieszanie, gdy kompilator wyświetli komunikat o błędzie dotyczący niepoprawnego użycia konstrukcji A, gdy rzeczywiście zamierzałeś zbudować B. Drugi kompilator może wywnioskować, że zamierzałeś B.
źródło
Ktoś podjął próbę glosariusza błędów GCC na Wikibooks jakiś czas temu, ale wygląda na to, że nigdy nie wystartował i nie został zaktualizowany.
Sekcja „Błędy” jest znacznie dalej niż sekcja „Ostrzeżenia”. Wygląda na to, że był przeznaczony dla G ++, ale nadal może tam być kilka informacji przydatnych dla twojego przyjaciela.
źródło
Oprócz powyższych odpowiedzi, zauważ, że większość kompilatorów nie ma kompleksowych glosariuszy błędów - byłoby to dużo pracy, ponieważ same komunikaty często się zmieniają, a jest ich całkiem sporo.
Najlepszym zamiennikiem glosariusza jest dostęp do Internetu. Ilekroć kompilator generuje błąd, którego nie rozumiesz, pociesz się, że jest mało prawdopodobne, abyś jako pierwszy go spotkał i był zdezorientowany. Szybka wiadomość Google z dokładną wiadomością często wystarcza, aby uzyskać mnóstwo informacji w łatwym do odczytania formacie, często z przykładowym kodem bardzo podobnym do Twojego.
Poza tym potrzebujesz czasu i znajomości języka oraz kompilatora. To i dobra rada udzielona przez Karla Bielefeldta .
źródło
Standard C używa wielu terminów, takich jak „lvalue” i „object” w sposób odmienny od innych języków programowania, a komunikaty kompilatora są często pisane w takich terminach. Użycie terminologii jest niespójne w niektórych częściach Standardu, ale każdy, kto chce się nauczyć języka C, powinien zapoznać się z projektami standardów C89, C99 i / lub C11, a także dokumentami uzasadniającymi je. Wyszukiwanie np. „Wersji roboczej C99” lub „uzasadnienia C89” powinno działać całkiem dobrze, chociaż może być konieczne uzyskanie dokumentu, którego oczekujesz. Chociaż większość kompilatorów obsługuje standard C99, warto wiedzieć, czym różni się on od standardu C89, a uzasadnienie C89 może oferować pewne historyczne tło, którego nie mają późniejsze wersje.
źródło
x=0x1e-x
powoduje błąd, to tak naprawdę nie wiem nic innego niż Standard ...Dziwi mnie, że nikt nie podał oczywistej odpowiedzi i, jak podejrzewam, najczęściej używanej w praktyce: po prostu nie czytaj komunikatów o błędach.
Zdecydowana większość wartości większości komunikatów o błędach polega po prostu na tym, że coś jest nie tak w takim i takim wierszu. Przez większość czasu po prostu patrzę na numer linii i przechodzę do tej linii. Moje „odczytanie” komunikatu o błędzie w tym momencie jest zwykle dokładnie tym, co przykuwa moje oko, nawet śladem. Jeśli nie jest od razu jasne, co jest nie tak na linii lub w jej pobliżu, wtedy faktycznie przeczytam wiadomość. Ten przepływ pracy jest jeszcze lepszy z IDE lub oprzyrządowaniem, które natychmiast rozpoznaje błędy i automatycznie realizuje sugestię Karla Bielefeldta, aby rozważyć tylko niewielkie zmiany.
Oczywiście komunikaty o błędach nie zawsze wskazują odpowiednią linię, ale często nie wskazują też właściwej przyczyny źródłowej, więc nawet pełne zrozumienie komunikatu o błędzie byłoby bardzo pomocne. Nie trwa długo, aby zorientować się, które komunikaty o błędach są bardziej niezawodne w zlokalizowaniu właściwej linii.
Z jednej strony większość błędów, które może popełnić nowicjusz, może być boleśnie oczywista dla doświadczonego programisty bez konieczności korzystania z kompilatora. Z drugiej strony są znacznie mniej prawdopodobne, że będą tak oczywiste dla początkującego (choć wielu będzie oczywistych, większość błędów to głupie błędy). W tym momencie całkowicie zgadzam się z Robertem Harveyem, nowicjusz musi po prostu lepiej poznać język. Nie da się tego uniknąć. Błędy kompilatora, które odnoszą się do nieznanych pojęć lub wydają się zaskakujące, powinny być postrzegane jako zachęta do pogłębienia znajomości języka. Podobnie w przypadkach, gdy kompilator narzeka, ale nie można zrozumieć, dlaczego kod jest nieprawidłowy.
Ponownie zgadzam się z Robertem Harveyem, że potrzebna jest lepsza strategia wykorzystania błędów kompilatora. Przedstawiłem niektóre aspekty powyżej, a odpowiedź Roberta Harveya podaje inne aspekty. Nie jest nawet jasne, co twój przyjaciel ma nadzieję zrobić z takim „glosariuszem”, i jest bardzo mało prawdopodobne, że taki „glosariusz” byłby bardzo przydatny dla twojego przyjaciela. Komunikaty kompilatora z pewnością nie są miejscem na wprowadzenie do pojęć języka 1, a „glosariusz” nie jest dla niego lepszym miejscem. Nawet z jasnym opisem, co oznacza komunikat o błędzie, nie powie ci, jak rozwiązać problem.
1 Próbuje tego jednak dokonać w kilku językach, takich jak Elm i Dhall (i prawdopodobnie Racket), a także kilka implementacji języków dla początkujących. W tym duchu doradztwo MSalters dotyczące zastosowania innej implementacji jest bezpośrednio istotne. Osobiście uważam takie rzeczy za nieprzekonujące i niezupełnie ukierunkowane na właściwy problem. Nie oznacza to, że nie ma sposobów na poprawianie komunikatów o błędach, ale dla mnie mają one tendencję do objaśniania przekonań kompilatora i ich podstaw.
źródło
Poinformuj swojego przyjaciela, aby wykonał następujące czynności, gdy napotka błąd, którego nie rozumie:
Błędy kompilatora mówią tylko o tym, czego kompilator nie rozumie o twoim kodzie, a nie o tym, co jest z nim nie tak. Takie podejście zajmuje mniej więcej tyle samo czasu, co w Google, przeglądając błąd i czytając niektóre dokumenty lub post StackOverflow, ale daje znacznie lepsze zrozumienie tego, co robisz źle.
Zmuszaj je również do częstej kompilacji, dopóki nie zaczną pracować nad projektami, których budowa zajmuje kilka minut, wykrywanie błędów przed dodaniem zbyt dużej ilości innego kodu bardzo pomaga.
Na koniec powiedz im, aby pracowali nad jedną rzeczą na raz, nie pracuj w wielu plikach bez kompilacji pomiędzy nimi, nie wprowadzaj wielu zależności jednocześnie itp.
źródło
Inną techniką byłoby, gdyby przyjaciel napisał z czasem własny słownik, gdy napotka różne komunikaty o błędach. Często najlepszym sposobem na nauczenie się czegoś jest nauczenie tego. Oczywiście, zanim skończy się słownik, prawdopodobnie już go nie będzie potrzebował.
Moje osobiste doświadczenie z GCC polega na tym, że każdy komunikat o błędzie odnosi się do „zwykłego” zestawu błędów. Na przykład, gdy GCC mówi „czy zapomniałeś &”, zwykle oznacza to, że zapomniałem nawiasów. Oczywiście, które błędy odpowiadają, które komunikaty o błędach będą zależeć od programisty, kolejny dobry powód dla znajomego, aby napisał własny słownik.
źródło