2010-10-20 11 views
5

Ad esempio, v'è la fonte:Come dire a gcc di codificare il codice con chiamate alla mia funzione ogni _line_ di codice?

void my_special_debugging_function(const char* function_name, const char* file_name, int line_number); 

void func1() { 
    func3(); 
    func4(); 
} 

void foo() { 
    func1(); 
    if(qqq) { 
     func2(); 
    }; 
    func3(); 
    func4(); 
    for(...) { 
     func5(); 
    } 
} 

Dovrebbe compilare come:

void my_special_debugging_function(const char* function_name, const char* file_name, int line_number); 

void func1() { 
    my_special_debugging_function("func1", "prog.c", 3); 
    func3(); 
    my_special_debugging_function("func1", "prog.c", 4); 
    func4(); 
    my_special_debugging_function("func1", "prog.c", 5); 
} 

void foo() { 
    my_special_debugging_function("foo", "prog.c", 8); 
    func1(); 
    my_special_debugging_function("foo", "prog.c", 9); 
    if(qqq) { 
     my_special_debugging_function("foo", "prog.c", 10); 
     func2(); 
     my_special_debugging_function("foo", "prog.c", 11); 
    }; 
    my_special_debugging_function("foo", "prog.c", 12); 
    func3(); 
    my_special_debugging_function("foo", "prog.c", 13); 
    func4(); 
    my_special_debugging_function("foo", "prog.c", 14); 
    for(...) { 
     my_special_debugging_function("foo", "prog.c", 15); 
     func5(); 
     my_special_debugging_function("foo", "prog.c", 16); 
    } 
    my_special_debugging_function("foo", "prog.c", 17); 
} 

Naturalmente, my_special_debugging_function dovrebbe essere in grado di utilizzare backtrace funzione.

C'è un'opzione di gcc per farlo? O c'è uno strumento per farlo a livello di codice sorgente? (Ad esempio generare altra souce C con la mia funzione)

@relatedHow to "interleave" C/C++ souce with my string (only inside functions at appropriate places)?

@relatedWhat profiler should I use to measure _real_ time (including waiting for syscalls) spend in this function, not _CPU_ one

+0

Non esattamente. Dovresti essere a conoscenza dei macro '__FILE__',' __LINE__' e '__func__', comunque. – nategoose

risposta

4

Vedere -finstrument-functions nella documentazione di GCC. Si consiglia di utilizzare dladdr() nella funzione di debug, che potrebbe anche richiedere il collegamento con -Wl,-export-dynamic.

+2

'-finstrument-functions' funziona a livello di funzione. Come farlo funzionare in linea? –

+0

@Vi: Non penso che ci sia un modo per dire a GCC di farlo, senza trucchi e modifiche al preprocessore al codice sorgente. – nategoose

+0

@nategoose, OK, chiedendo di nuovo i trucchi per il codice sorgente: http://stackoverflow.com/questions/3989992/how-to-interleave-cc-souce-with-my-string-only-inside-functions-at -appropri –

0

Come indicato nel altra risposta, I don't think that there is any way to tell GCC to do that, without preprocessor tricks and edits to the source code. – nategoose

2

Se si utilizza una versione gcc> = 4.5 è possibile write a gcc plugin che elabora l'AST nel modo che ti piace. Ma quella soluzione sarebbe dipendente dal compilatore.

È inoltre possibile obtain AST from eclipse CDT e rigenerare il codice C da tale input.

0

Si può fare facilmente usando aspectC++. Ottieni questo compilatore da aspectc.org Ecco un aspetto semplice che soddisfa le tue esigenze. Trace.ah

#ifndef __trace_ah__ 
#define __trace_ah__ 
#include <cstdio> 
#include <iostream> 
using namespace std; 
template <int I> struct ArgPrinter 
{ 
template <class JP> static inline void work (JP &tjp) { 
ArgPrinter<I - 1>::work (tjp); 
cout << *tjp.template arg<I - 1>() << " "; 
} 
}; 
template <> struct ArgPrinter<0> 
{ 
template <class JP> static inline void work (JP &tjp) {} 
}; 


aspect trace { 
int depth=-1; 
pointcut virtual methods() = "% ...::%(...)"; 

template <class JP> void print_args (JP &tjp) 
    { 
     ArgPrinter<JP::ARGS>::work (tjp); 
    } 

advice execution (methods()) : before() 
{ 
    depth++; 
    cout << "Enter -> " << JoinPoint::signature() <<" Depth:"<<depth<< " ARGS " << JoinPoint::ARGS <<" ("; 
    tjp->arg(0); 
    print_args (*tjp); 
    cout<<")"<<endl; 
    cout<< "console--"<<endl; 
} 

advice execution("% ...::%(...)" && !"void ...::%(...)") : after() 
{ 
    cout<< "--console"<<endl; 
    JoinPoint::Result res = *tjp->result(); 
    cout << "Exit <- " << tjp->signature()<< " Depth: "<<depth<< " RET " << res<<endl; 
    depth--; 
} 
advice execution("void ...::%(...)") : after() 
{ 
    cout<< "--console"<<endl; 
    cout << "Exit <- " << tjp->signature()<< " Depth: "<<depth<< " RET void"<<endl; 
    depth--; 
} 
}; 
#endif 

Compilare questo aspetto con il vostro progetto usando il compilatore aC++ quindi eseguire il programma. Quindi dovresti vedere la traccia nella console. Happy Tracing!

Problemi correlati