[so] [Tech Q] Print debugging

Adrian Scoica adrian.scoica at gmail.com
Sun Mar 6 22:55:49 EET 2011


>
> 1) Când faci debugging, vrei să nu afișezi doar un mesaj ci, de dorit,
> fișierul și linia care a generat mesajul.

Pentru linia curenta din fisier, se poate folosi macro-ul __LINE__
(cate 2 caractere '_'). __LINE__ functioneaza fie in mod absolut
(numarand de la inceputul fisierului), fie in mod relativ (numara
incremental de la ultima directiva #line din fisier). De exemplu:

/* asta e linia 4 */
printf("%d",__LINE__); /* se afiseaza 5 */
#line 100
printf("%d",__LINE__); /* se afiseaza 100 */

Motivul pentru care se afiseaza 100 si nu 101 este ca numerotarea
trebuie sa inceapa de la linia _dupa_ #line, deoarece nu se poate afla
nici o alta instructiune pe aceeasi linie cu o directiva (si astfel,
linia 100 nu ar exista deloc).

> 2) Nu vrei să afișezi doar un string ci poate o afișare de forma printf.
> Adică LOG("x = %d, y = %d\n", x, y);

In C++, poti afisa o variabila intr-un macro doar stiindu-i numele. De
exemplu, daca ai:

#define LOG(a) (std::cerr<< a << "\n")

atunci poti afisa astfel:

LOG("valoare(x): " << x << ", valoare(y) " << y);

Trebuie sa renunuti la parantezele din jurul lui a, pentru ca vrei ca
primul operator "<<" care sa se aplice sa fie primul din macro (altfel
nici nu ar avea sens). Dupa procesare o sa arate asa:

std::cerr << "valoare(x) " << x << ", valoare(y) " << y << "\n";

In modul asta poti amesteca orice fel de output.

Evident, se poate face ceva similar si in C. Varianta la care ma
gandesc eu este sa oglindesti pur si simplu printf:

#define LOG(a) printf a

Acest macro trebuie apelat astfel:

LOG(("x = %d, y = %d", x, y)); // dupa procesare arata ca si clasicul printf

Motivul pentru care avem nevoie de doua seturi de paranteze vine de la
modul in care se interpreteaza parametrii unui macro. Daca am fi pus
un singur set de paranteze, atunci am fi apelat astfel:

LOG("x = %d, y = %d", x, y);

iar preprocesorul interpreteaza acest macro ca avand trei parametri
separati prin virgula:

"%x = %d, y = %d"
x
y

Daca punem un set dublu de paranteze, se interpreteaza asa cum vrem noi.

Mi se pare mult mai estetica metoda C de a defini macro-ul daca scrii
cod cu apeuri de sistem (stringul afisat este mai scurt si mai lizibil
daca se folosesc specificatori de format).

Metoda C++ este mai eleganta atunci cand ai nevoie si de afisarea de
structuri in mod uniform. De exemplu, daca "s" este o structura, e mai
frumos sa scrii:

LOG("Parametrii sunt: " << s);

decat

LOG(("Parametrii sunt: %s", struct_to_string(s)));

Partea urata aici este faptul ca e nevoie de un string intermediar,
care trebuie sa fie static ca sa nu faca memory leak (si suficient de
lung, si... mai sunt probleme). Bineinteles, poti afisa si membrii
direct, dar nu e o solutie care scaleaza foarte bine.

In definitiv, oricum e acealsi lucru, pentru ca in ambele cazuri
trebuie sa scrii cod prin care sa explici cum anume se afiseaza
structura aia (care membri, cu ce text...).

Exista si in C o metoda mai generica? :-?


More information about the so mailing list