Chybovník – chyba P213

Úmyslné využívání vedlejších efektů funkcí

Popis chyby: Chyba spočívá v tom, že některá z funkcí programu modifikuje ve svém těle proměnnou (tedy mění její hodnotu), která je deklarovaná v programu jako globální, aniž by jí tato proměnná byla předaná odkazem (tedy adresou jejího umístění v paměti prostřednictvím ukazatele).

Proč je to špatně? Pokud funkce modifikuje globální proměnnou, která jí není předána jako parametr odkazem, dochází ke změně stavu programu (neboť každá globální proměnná je nutně stavovou proměnnou celého programu). Zároveň ovšem – tím, že předmětná funkce nepřebírá danou globální proměnnou jako parametr (odkazem, realizovaným ukazatelem, aby bylo možné hodnotu proměnné v těle funkce změnit), není zřejmé, že k modifikaci hodnoty uvnitř funkce dojde. Tzn. např. při týmovém programování to představuje poměrně značný problém, neboť ostatní členové týmu (pokud si tělo funkce nepřečtou) nevědí, že volání takové funkce může změnit stav programu.

Dalším problémem je pak reusabilita takové funkce: Půjde pochopitelně zavolat pouze v programu, ve kterém existuje příslušná globální proměnná, kterou tato funkce modifikuje. Uložení takovéto funkce např. do knihovny pro další použití je tedy nemožné.

Ukázka problematického kódu:
   1 :  #include "sysutils.h"
   2 :            
   3 :  int screen_width;
   4 :            
   5 :  void setup() {
   6 :       screen_width = system_get_screen_width();
   7 :  }
   8 :  
   9 :  ...
  10 :  
  11 :  int main() {
  12 :       setup();
  13 :       run();
  14 :       shutdown();
  15 :  }

Ukázka správnějšího kódu:
   1 :  #include "sysutils.h"
   2 :            
   3 :  int screen_width;
   4 :            
   5 :  void setup(int *scr_w) {
   6 :       *scr_w = system_get_screen_width();
   7 :  }
   8 :  
   9 :  ...
  10 :  
  11 :  int main() {
  12 :       setup(&screen_width);
  13 :       run();
  14 :       shutdown();
  15 :  }


Nejlepší by v tomto případě ovšem bylo se globální proměnné zcela vyhnout a celý problém řešit jiným způsobem, např. tak, že by funkce setup() vracela třeba ukazatel na dynamicky vytvořenou instanci struktury, která by udržovala celou "konfiguraci" programu.

<< Zpět na chybovník