[so] [Tech Q] Print debugging

Adrian Scoica adrian.scoica at gmail.com
Sun Mar 6 17:17:14 EET 2011


>
> ---
> static enum {
>        FALSE = 0,
>        TRUE
> } debug = TRUE;
>
> ....
>
>        /* undeva intr-o functie */
>
>        if (debug == TRUE)
>                printf("debug message\n");
> ....

Problema la metoda asta (pe langa faptul ca are 2 linii) este
comparatia. Chiar daca vei compila codul intr-o configuratie "release"
(in care nu se mai face testing), la fiecare apel de functie, se
efectueaza o instructiune in plus (si care mai e si jump pe deasupra).

O metoda mai eleganta este sa definesti un macro de genul:

#ifdef _DEBUG
#define LOG(a) (std::cerr << (a) << "\n")
#else
#define while(0)
#endif

Poate fi si mai complicat, dar nu este relevant acum.

Se observa ca lipseste aici ";" pentru ca vreau sa ma forteze
compilatorul sa pun ";" dupa LOG(a); - asa o sa arate mai normal
codul.

while(0) este pus acolo din cauza unei smecherii de sintaxa. Daca
aveai in codul orginal:

if (x == 5) LOG("X ia valoarea 5"); else x=6;

si compilezi fara _DEBUG, atunci obtii

if (x == 5) while(0); else x = 6;

oricum compilatorul scoate while(0) de acolo, nu produce overhead.
Putea la fel de bine sa fie si for(;0;) sau do { } while(0).

NU putea sa fie in schimb if(0), pentru ca s-ar fi reinterpretat
else-ul de mai jos ca fiind al lui.

De asemenea, in C++ am pus paranteze in jurul lui (a) din macro din
motive de chaining. De exemplu, daca as vrea sa scriu LOG(s <<
arbore), unde s este un obiect de tip stringstream sau string, si
arbore e un arbore de parsare definit de mine, atunci se executa

op<< ( op<< (std::cerr, s), arbore)

si nu cum as fi vrut eu sa fie:

op<< ( std::cer, s << arbore )

Aceleasi smecherii merg si in C, evident, mai putin stream-urile si
operatorii. Se poate defini de exemplu, un macro care sa inlocuiasca
printf();

In aceeasi ordine de idei, se pot defini niveluri diferite de
debugging, care sa activeze sau nu un volum mai mare sau mai mic de
debugging. De exemplu:

_DEBUG_SEM 1 - face logging la arborele semantic, doar erorile generale
_DEBUG_SEM 2 - face logging la arborele semantic, eticheta fiecarui nod
_DEBUG_SEM 3 - face logging de la inceput si pana la sfarsit

Similar ca mai sus, pui intr-un header:

#if _DEBUG_SEM<1
... activeaza LOG_ERR
#if _DEBUG_SEM<2
... activeaza LOG_TAG
#if _DEBUG_SEM<3
... activeaza LOG_FULL

Astfel, poti contola cat de in detaliu vrei sa faci debugging definind
_DEBUG_SEM={1,2.3}. Evident, totul ar trebui protejat de #ifdef [ ...
] #endif.

Pare complicat, dar daca le scrii odata, le poti folosi cu succes in
toate sursele de mai tarziu.


More information about the so mailing list