Chilijskie łososie mają anemię

2010-02-21 15:00

Źródło: Glenn Oliver/Visuals Unlimited/Getty Images

Tak, to stuprocentowa prawda – większość tych ryb w hodowlach w Chile jest dotknięta tą chorobą. Efektem tego będzie na pewno wzrost cen łososia również w sklepach.
No dobrze, ale co z tego – a dokładniej, czemu o tym piszę tutaj (bo fakt, że lubię dania z tych ryb pewnie nie jest wystarczającym uzasadnieniem ;])?… Otóż tytuł tej notki to doskonały przykład informacji, która jest prawdziwa, dokładna, a jednocześnie całkiem nieprzydatna i wywołująca tylko zdziwienie u odbiorcy.

To zupełnie tak, jak z niektórymi… komunikatami o błędach, produkowanymi przez kompilator C++ pracujący w ramach Visual Studio. Z punktu widzenia analizy kodu przez tenże kompilator mają one sens, jednak dla czytającego je programisty często mówią tyle co nic.
Z czasem aczkolwiek można nabrać wprawy i zacząć domyślać się, co tak naprawdę kompilator “miał na myśli”, produkując tę czy inną wiadomość o błędzie. To jednak wciąż wybitnie niepraktyczne i dlatego postaram się dzisiaj pomóc w tej kwestii, wyjaśniając prawdziwe znaczenie niektórych komunikatów wypluwanych przez Visual C++:

  • error C2146: syntax error : missing ‘;’. Czasami powodem tego błędu jest faktycznie brak średnika (np. na końcu definicji klasy). Często jednak pojawia się w – na oko – poprawnych deklaracjach zmiennych. Wtedy przyczyną jest nieznajomość typu tej zmiennej, więc pośrednio jest to brak dołączonego nagłówka, literówka w deklaracji tego typu, itp.
  • error C2181: illegal else without matching if. Pozornie “luźny” else to często efekt postawienia o jednego średnika za dużo – mianowicie średnika po bloku if. Jeśli używamy makr do zastępowania powtarzających się fragmentów kodu, to może tu chodzić o niepoprawne zdefiniowanie takiego makra.
  • error C2301: left of ‘->foo’ must point to class/struct/union. Ten i podobne błędy: C2302, C2510 oznaczają tyle, że kompilator nie rozpoznaje nazwy stojącej przed operatorem wyłuskania ->, . (kropką) lub ::. Niekoniecznie musi to znaczyć, że została ona źle zadeklarowana (i nie jest klasą/strukturą/unią) – najczęściej po prostu nie została zadeklarowana w ogóle.
  • error C2360: initialization of ‘foo’ is skipped by ‘case’ label. Ten komunikat (oraz analogiczny C2361) jest spowodowany brakiem nawiasów klamrowych otaczających bardziej skomplikowane kawałki kodu zawarte w poszczególnych przypadkach instrukcji switch (takie, które zawierają deklaracje nowych zmiennych). Bardzo podobny błąd dotyczy też używania etykiet i instrukcji goto, które, jak wiadomo, są złem potwornym (w tym przypadku żartuję oczywiście).
  • error C2440: ‘conversion’ : cannot convert from ‘Foo’ to ‘Bar’. Jeśli któryś z występujących w komunikacie (lub podobnym C2446) typów nie jest typem wbudowanym, to najpewniej brak tutaj dołączenia jakiegoś nagłówka, który daną konwersję by definiował. Inna możliwa przyczyna to przypuszczenie, że kompilator będzie na tyle sprytny i zastosuje dwie konwersje przez jakiś typ pośredni; niestety tak nie jest – naraz może być stosowana tylko jedna niejawna konwersja zdefiniowana przez programistę.
  • error C2512: ‘Foo’ : no appropriate default constructor available. Błąd ten może naprawdę zbić z tropu, o ile nie wiemy dokładnie, co jest jego przyczyną. Żeby się objawił, nie potrzeba tworzyć żadnych obiektów – wystarczy odziedziczyć po klasie, która nie ma domyślnego konstruktora. W takiej sytuacji musimy w każdym konstruktorze klasy potomnej zapewnić wywołanie konstruktora klasy bazowej (na liście inicjalizacyjnej) – albo po prostu dodać ten brakujący konstruktor domyślny w klasie bazowej.
  • error C2621: member ‘Foo::Bar’ of union ‘Foo’ has copy constructor. Typowym scenariuszem objawienia się tego błędu jest próba stworzenia unii zawierającej pole typu (w)string. Nie jest to możliwe – ze względu na obecność konstruktora kopiującego – i choć teoretycznie możliwe jest obejście tego faktu, stosowanie go jest bardzo, bardzo złym pomysłem. Lepiej po prostu przymknąć oko na “marnotrawstwo pamięci” i zmienić unię w strukturę.

Nie jest oczywiście możliwe wyliczenie wszystkich okoliczności, w których może objawić się każdy możliwy błąd. Powyższa lista jest więc trochę subiektywna w tym sensie, że zawiera tylko te pozycje, które przytrafiły mi się osobiście podczas kodowania. Bardziej doświadczeni programiści pewnie mogliby ją znacznie poszerzyć.

Tags: , ,
Author: Xion, posted under Programming »


2 comments for post “Chilijskie łososie mają anemię”.
  1. Kacper Kołodziej:
    February 22nd, 2010 o 9:34

    Kolejny super wpis. Chociaż z Visual Studio nie korzystam już od dawna, to lista bardzo się przyda, bo wxGlade wywala (czasem) podobne błędy.

  2. Reg:
    February 28th, 2010 o 12:22

    Dobre! Myślę, że mógłbyś nawet skopiować tą listę na wiki.gamedev.pl. Może ktoś coś tam jeszcze doda i powstaje encyklopedia błędów C++, czy raczej słownik tłumaczący błędy kompilatora na “normalny” język :)

Comments are disabled.
 


© 2017 Karol Kuczmarski "Xion". Layout by Urszulka. Powered by WordPress with QuickLaTeX.com.