Асерти су провере истинитости одређеног израза. Уколико евалуација израза који се прослеђује макроу „assert” за резултат даје нулу, програм се прекида уз поруку о изразу, имену фајла и линији. Порука може да се разликује у зависности од компајлера и система на коме се програмира, али ће све мање-више имати одређену информацију о томе где се асерт десио.
Када се програм искомпајлира са дефинисаним макроом „NDEBUG”, асерти нестају (макро assert бива дефинисан као ((void)0) и избачен као линија без ефекта).
Током развоја, важно је користити програм компајлиран без овог макроа (односно са укљученим асертима).
Један тривијалан пример:
#include <assert.h>
#include <string.h>
int mojstrlen(const char * const p)
{
assert(p != NULL);
return strlen(p);
}
У примеру се види предност (и мана) овог приступа. Иако не можемо да забранимо кориснику функције да проследи NULL вредност, омогућујемо му да открије своју грешку у току развоја. Такође, само кратким погледом на функцију кориснику (програмеру) ће бити јасно да треба да обезбеди не-нул вредност.
Сама чињеница да асерти не постоје у коначном програму који се испоручује их чини адекватним само за оне случајеве који не смеју да се десе на терену, али истовремено их чине идеалним за време тестирања.
Рецимо да хоћемо да направимо робусну библиотеку и затим је дистрибуирамо корисницима од којих не можемо да очекујемо да знају да вредност показивача не сме да буде нула, онда асерт није довољан, а можда ни адекватан. У том случају би било примереније урадити нешто овако:
int mojstrlen(const char *const p)
{
if (p == NULL)
return 0;
return strlen(p);
}
Као правило, ја користим асерте на функцијама које нису експортоване из библиотека, него су намењене за коришћење унутар једног програма. Како често није очигледно шта одређен логички исказ проверава, онда уз исказ додам и текст који описује проверу. У примеру горе, то би изгледало овако:
int mojstrlen(const char * const p)
{
assert(p != NULL && !!"Pokazivac 'p' ne sme biti NULL");
return strlen(p);
}
Нема коментара:
Постави коментар