Search code examples
c++logginggprofcallgrind

Logging code execution in C++


Having used gprof and callgrind many times, I have reached the (obvious) conclusion that I cannot use them efficiently when dealing with large (as in a CAD program that loads a whole car) programs. I was thinking that maybe, I could use some C/C++ MACRO magic and somehow build a simple (but nice) logging mechanism. For example, one can call a function using the following macro:

#define CALL_FUN(fun_name, ...) \
    fun_name (__VA_ARGS__);

We could add some clocking/timing stuff before and after the function call, so that every function called with CALL_FUN gets timed, e.g

#define CALL_FUN(fun_name, ...) \
   time_t(&t0);                 \
   fun_name (__VA_ARGS__);      \
   time_t(&t1);

The variables t0, t1 could be found in a global logging object. That logging object can also hold the calling graph for each function called through CALL_FUN. Afterwards, that object can be written in a (specifically formatted) file, and be parsed from some other program.

So here comes my (first) question: Do you find this approach tractable ? If yes, how can it be enhanced, and if not, can you propose a better way to measure time and log callgraphs ?

A collegue proposed another approach to deal with this problem, which is annotating with a specific comment each function (that we care to log). Then, during the make process, a special preprocessor must be run, parse each source file, add logging logic for each function we care to log, create a new source file with the newly added (parsing) code, and build that code instead. I guess that reading CALL_FUN... macros (my proposal) all over the place is not the best approach, and his approach would solve this problem. So what is your opinion about this approach?

PS: I am not well versed in the pitfalls of C/C++ MACROs, so if this can be developed using another approach, please say it so.

Thank you.


Solution

  • Well you could do some C++ magic to embed a logging object. something like

    class CDebug 
    {
    CDebug() { ... log somehow ... }
    ~CDebug() { ... log somehow ... }
    
    };
    

    in your functions then you simply write

    void foo()
    {
       CDebug dbg;
        ...
    
       you could add some debug info
    
    
       dbg.heythishappened()
    
       ...
    }  // not dtor is called or if function is interrupted called from elsewhere.