Jak na pro­jek­ty v ja­zy­ce C

© Damig, 2004 – 2023
Koncept

Ladění a testování programů
Používání makra assert

Makro assert neslouží přímo pro ladění programů. Jeho použití lze nazvat jako techniku sebeobranného programování. Programujete tak, že necháte kód, aby vás neustále hlídal, zda neděláte chyby.

Hlavní myšlenka je jednoduchá. Do zdrojového kódu programu vložíte hlavičkový soubor assert.h a umístíte na vhodná místa svého kódu volání makra assert. Jeho parametrem je logický výraz, o kterém jste přesvědčení, že bude za všech okolností pravdivý. Pokud během testování programu dojde k situaci, že se tento logický výraz vyhodnotí jako nepravdivý, znamená to, že váš předpoklad neplatí a v programu je chyba. Makro assert proto program ukončí a vypíše chybové hlášení o tom, na kterém řádku došlo k porušení předpokladu.

Makro assert se velice často používá v programech s ukazateli a pro testování parametrů funkcí. Může se ale používat i pro testování jiných invariantů, tj. podmínek, jejichž výsledek by měl zůstat stejný nezávisle na použití programu.

#include <assert.h>

int listPushBack(TListNode **first, int value)
{
  // Zde se předává ukazatel odkazem. Je-li parametr first
  // roven NULL, jde určitě o chybu programátora.
  assert(first != NULL);

  if (*first == NULL)
  {
     *first = newNode(value);
     if (*first == NULL) // toto se makrem assert testovat nesmí
       return ENOMEM;
  }
  else
  {
    TListNode *node = *first;
    assert(node != NULL); // tohle musí být pravda

    while (node->next != NULL)
      node = node->next;

    assert(node != NULL); // tohle musí být pravda

    node->next = newNode(value);
    if (node->next == NULL) // toto se makrem assert testovat nesmí
      return ENOMEM;
  }

  return EOK;
}
Makro assert ve funkci hlídá, zda ukazatele na kritických místech neobsahují prázdnou adresu. Pokud k tomu dojde, je to chyba programátora a program se přeruší s chybovým hlášením. Pokud by k chybě mohlo dojít vlivem běžného používání programu, není vhodné makro assert používat. V tomto případě by bylo potřeba testovat hodnoty standardním způsobem a vracet z funkce chybové kódy.

Definice makra assert se nachází v hlavičkovém souboru <assert.h>. Pokud jste si jistí, že program je dostatečně otestován, lze chování makra assert globálně vypnout tak, že před místem vložení hlavičkového souboru assert.h vložíte definici symbolu NDEBUG. Potom se při překladu každé volání makra nahradí prázdným kódem a test se vůbec do výsledného programu nezahrne.

POZOR! Makro assert nelze používat jako náhradu běžných testů, které jsou součástí funkčnosti programu. Je potřeba si uvědomit, že funkci makra assert lze vypnout. Pokud na vyhodnocení podmínky závisí funkčnost programu (vyhodnocení podmínky má například vedlejší efekt), je potřeba místo makra assert použít test pomocí příkazu if a v případě detekce chyby tisknout odpovídající chybové hlášení.

Makro assert se rozhodně naučte používat. Jeho správné používání vede ke kvalitnějším programům s menším počtem chyb. Kromě detekce chyb má makro assert ještě jeden pozitivní efekt. Nutí programátora přemýšlet nad vlastním kódem, což nikdy nemůže škodit.

#define NDEBUG
#include <assert.h>
Definice symbolu NDEBUG před vložením hlavičkového souboru způsobí, že se makro assert při překladu nahradí prázdným kódem (mezerou).