[c++] logging van Process Id mbv een macro

Pagina: 1
Acties:

  • liquid_ice
  • Registratie: Februari 2001
  • Laatst online: 31-10 08:52
Ok het eventjes wat te versimpelen zeg ik eventjes dat ik een logging class heb met 2 type logging

Info en Error

gedefinieerd als:
#define LogError(CompId, Msg) printf(Msg);
#define LogError1(CompId, Msg, data1) printf(Msg, data1);

#define LogInfo(CompId, Msg) printf(Msg);
#define LogInfo2(CompId, Msg, data1) printf(Msg, data1);

en zo ook voor meerdere parameters.

Wat ik graag wil is aan de error automatisch aan tag "ERROR" plakken.
Ook wil ik graag dat het systeem weergeeft vanuit welk PID dat de melding komt.
Hiervoor heb ik een functie getpid() welke een int terug geeft.

Alleen lukt het me maar niet ok dat met deze macro's voor elkaar te krijgen.

Klus page: http://klusthuis.blogspot.com


  • DataGhost
  • Registratie: Augustus 2003
  • Laatst online: 18-11 15:57

DataGhost

iPL dev

Je kan die functie toch gewoon in je macro neerzetten zodat ie aangeroepen wordt op de plaatsen waar je die macro neerzet? Dat je geen gelijke functionaliteit krijgt met enkel een macro (dus geen functie-calls?) is nogal logisch, daar het proces-ID nog niet bekend is tijdens het compileren.
Volgens mij kan je zoiets doen als
#define LogError(CompId, Msg) printf("ERROR(%d): " Msg, getpid());
#define LogError1(CompId, Msg, data1) printf("ERROR(%d): " Msg, getpid(), data1);

  • liquid_ice
  • Registratie: Februari 2001
  • Laatst online: 31-10 08:52
Denk dat ik iets vergeten ben te vermelden...

Als ik de LogError functie gebruik zal het iets zijn als:

LogError(testId, "Melding wat de errorcode is: %d", errorcode)

waarbij testId een waarde is die nu nog niet van belang is.

de string "Melding wat de error is: %d" komt dus in de Msg te staan en de errocode zal wel moeten worden afgedrukt.

Bij het voorbeeld hierboven wil ik op het scherm zien:
"ERROR PID= 513: Melding wat de error is: 5"
(er van uitgaande dat de PID 513 is he)

Bij:
#define LogError(CompId, Msg) printf("ERROR(%d): " Msg, getpid());

dan word de error message zelf niet afgedrukt

[ Voor 13% gewijzigd door liquid_ice op 21-05-2008 09:50 ]

Klus page: http://klusthuis.blogspot.com


  • DataGhost
  • Registratie: Augustus 2003
  • Laatst online: 18-11 15:57

DataGhost

iPL dev

Bij mij wel, waarom zou het niet werken?
# cat logmeuk.c && gcc logmeuk.c -o logmeuk
#define LogError(Msg) printf("ERROR(%d): " Msg, getpid())
int main() { LogError("waa\n"); return 0; }
# ./logmeuk                                
ERROR(10570): waa

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22:10

.oisyn

Moderator Devschuur®

Demotivational Speaker

Je leest niet goed. De aanroep
C++:
1
2
3
4
int main()
{
   LogError1(1, "Hallo, dit is mijn error: %d", 1234);
}

werkt dan niet.

Maar je moet dat helemaal niet in de macro oplossen. Je moet gewoon een aparte functie maken die wordt aangeroepen
C++:
1
2
3
4
5
6
7
8
9
10
11
void LogErrorImpl(const char * msg, ...)
{
    printf("ERROR PID=%d: ", getpid());
    va_list v;
    va_start(v, msg);
    vprintf(msg, v);
    va_end(v);
}

#define LogError(CompId, Msg) LogErrorImpl(Msg)
#define LogError1(CompId, Msg, data) LogErrorImpl(Msg, data)


Overigens hoewel niet onderdeel van standaard C++ ondersteunen de meeste moderne compilers wel de vararg macro features van C99. Je hoeft dus geen LogError1 t/m LogErrorN te definieren voor N aparte parameters.

.edit: zonder vararg macro's kan het trouwens ook, door de macro's niet als functies te definieren
C++:
1
#define LogError    LogErrorImpl

Moet je wel even zorgen dat de meegegeven CompId ook een parameter is van LogErrorImpl(). De vraag die je jezelf vervolgens kunt stellen is waarom je überhaupt een macro nodig hebt.

[ Voor 17% gewijzigd door .oisyn op 21-05-2008 11:33 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Zoek je niet zo iets? Ik gebruik dit om API calls automatisch te debuggen/loggen.

C++:
1
2
3
4
5
6
#define CUDA_CALL(str) \
    if ((str) != 0) { \
    printf("Warning: %s returned non-zero (line: %d file: %s)\n", #str, __LINE__, __FILE__); \
    printf("Error code: %d\nError message: %s\n", cudaGetLastError(), cudaGetErrorString(cudaGetLastError())); \
    exit(1);\
    } 

Het punt is dat je er een # voorzet om er een string van te maken in een macro.

Bv als dit nu fout gaat:

C++:
1
    CUDA_CALL(cudaMemcpy(dev_vbo, dev_Y1, sizeof(State)*g_const.nr_balls, cudaMemcpyDeviceToDevice));

Krijg je als melding,
Warning: cudaMemcpy(dev_vbo, dev_Y1, sizeof(State)*g_const.nr_balls, cudaMemcpyDeviceToDevice) returned non-zero (line: 42 file: main.cu)
Error code: 1
Error message: CUDA not initialized

In jouw geval dus:
C++:
1
#define LogError(CompId, Msg) printf("ERROR(%d): %s", getpid(), #Msg);

[ Voor 34% gewijzigd door Zoijar op 21-05-2008 12:28 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22:10

.oisyn

Moderator Devschuur®

Demotivational Speaker

Maar hij wil dus de inhoud van variabelen loggen, vandaar de LogError1 macro die een extra parameter heeft. Dat kan natuurlijk niet door de invoer te stringifyen.

Overigens zou ik nog een do { ... } while(0) om je CUDA_CALL heenzetten, anders krijg je mooie onverwachte bijwerkingen zoals hier:
C++:
1
2
3
4
if (someCondition)
    CUDA_CALL(aap());
else
    DoeIetsAnders();

:P

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Coca-Cola
  • Registratie: Maart 2001
  • Laatst online: 18:51
Of gewoon { en } toch? Ik zag in Code Complete bij dit voorbeeld geen do while staan ;)

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22:10

.oisyn

Moderator Devschuur®

Demotivational Speaker

do..while(0) is beter, dan wordt de puntkomma aan het eind ook verplicht. En als je 'm helemaal als een functie wilt laten gedragen (zodat je 'm midden in expressies kunt gebruiken), kun je de macro het beste direct naar een functie laten routen:

C++:
1
2
3
4
5
6
7
8
9
10
11
bool CudaLogCall(int ret, const char * str, int line, const char * file)
{
    if (!ret)
    {
        printf("Warning: %s returned non-zero (line: %d file: %s)\n", str, line, file);
        printf("Error code: %d\nError message: %s\n", cudaGetLastError(), cudaGetErrorString(cudaGetLastError()));
    }
    return ret;
}

#define CUDA_CALL(str) CudaLogCall((str), #str, __LINE__, __FILE__)

Dit geniet eigenlijk mijn grootste voorkeur. Iets wat eruit ziet als een functie kan zich beter maar ook letterlijk gedragen als een functie :)

[ Voor 91% gewijzigd door .oisyn op 21-05-2008 13:45 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Hmm dan snap ik het niet. Als je de inhoud wilt afbeelden laat je toch gewoon die pound weg?

Die laatste macro is idd een stuk netter.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22:10

.oisyn

Moderator Devschuur®

Demotivational Speaker

Zoijar schreef op woensdag 21 mei 2008 @ 16:11:
Hmm dan snap ik het niet. Als je de inhoud wilt afbeelden laat je toch gewoon die pound weg?
Hij heeft nu:
C++:
1
2
3
4
5
6
#define MyPrintfMacro(msg, data)    printf(msg, data)

int main()
{
    MyPrintfMacro("Hallo daar, hier een getal: %d\n", 1234);
}


Nu wilt hij vóór die printf, een "ERROR: %d" printen, waarbij die %d de PID van z'n proces is. Zonder de macro-aanroep aan te passen dus. In feite heeft ie dus twee format strings (de "ERROR: %d", en de eerste parameter van de macro), die je niet met 1 printf() call af kunt drukken.

[ Voor 3% gewijzigd door .oisyn op 21-05-2008 16:17 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • DataGhost
  • Registratie: Augustus 2003
  • Laatst online: 18-11 15:57

DataGhost

iPL dev

Wat een onzin. Als je het doet zoals ik het liet zien kan je gewoon argumenten door blijven geven hoor... ik had het maar bij één van de macro's aangepast met het idee dat hij de tweede zelf wel aan zou kunnen passen. De beste manier om logging te bouwen heb ik daarbij in het midden gelaten.

# cat logmeuk.c && gcc logmeuk.c -o logmeuk
#define LogError1(Msg, Data) printf("ERROR(%d): " Msg, getpid(), Data)
int main() { LogError1("waa %d\n", 42); return 0; }
# ./logmeuk                                
ERROR(19704): waa 42
# gcc logmeuk.c -E
<knip>
int main() { printf("ERROR(%d): " "waa %d\n", getpid(), 42); return 0; }

Dat wordt gewoon een string concatenation en het argument wordt gewoon het tweede (derde) argument voor printf.

[ Voor 16% gewijzigd door DataGhost op 21-05-2008 23:28 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22:10

.oisyn

Moderator Devschuur®

Demotivational Speaker

Hmm goed punt, de string concatenatie had ik niet aan gedacht (en niet gezien in je eerdere post). Dat is idd een goede oplossing.

Hoewel ik nog steeds pleit voor een gewone functie, hoef je ook niet N macro's te maken om 0 t/m N-1 parameters te ondersteunen.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • liquid_ice
  • Registratie: Februari 2001
  • Laatst online: 31-10 08:52
Ik heb het nu op de manier van DataGhost gedaan...

Maar de varargs manier van .oisyn wil ik nog wel gaan toepassen.
Vind het wel een mooi idee om niet meer N macro's te hebben :D

Klus page: http://klusthuis.blogspot.com

Pagina: 1