2016-08-02 31 views
3

Ich bin auf der Suche nach einer Möglichkeit, Code automatisch am Anfang und am Anfang einer Funktion hinzuzufügen. Die Idee ist, dass ich den laufenden Code später profilieren möchte. Zum Beispiel habe ich die Funktionen:Fügen Sie einen eindeutigen Code zu Beginn und Ende der Funktion in c

void helloWorld(){ 
    printf("Hello World!\n"); 
} 

void worldHello(){ 
    printf("World hello!\n"); 
} 

Ich mag würde eine Art von Makro haben, die sie erweitert:

void helloWorld(){ 
    printf("Function id 1 enter"); 
    printf("Hello World!\n"); 
    printf("Function id 1 exit"); 
} 

void worldHello(){ 
    printf("Function id 2 enter"); 
    printf("World hello!\n"); 
    printf("Function id 2 exit"); 
} 

Wo die ID eindeutig gegeben wird jedes Mal, wenn ich meinen Makro verwenden. Kann jemand eine gute Idee haben, wie ich das erreichen könnte? Ich habe das "__COUNTER__" in GCC angeschaut, aber es hat nicht wirklich funktioniert, wie ich es wollte.

+3

Haben Sie in gprof geschaut? –

+0

Zu viel mit den Sprachgrundlagen zu fummeln - wie zum Beispiel Funktionsdeklarationen mit etwas Makrozauber zu ersetzen, das automatisch Code hinzufügt - könnte auf kurze Sicht eine gute Idee sein. Aber Menschen (einschließlich Sie selbst) werden Sie langfristig dafür hassen. ;-) Dave und Downvoter hier abkommend, werfen Sie einen Blick auf bereits existierende Lösungen. – DevSolar

+0

Nein, ich wusste nichts darüber, aber ich benutze meinen Code auf einem Mikroprozessor, und ich versuche, die ID der aktivierten Funktionen mit GPIO-Pins zu setzen und die Ausgabe auf einer anderen Hardware zu lesen und zu analysieren. Ich habe sehr strenge Zeitvorgaben und kann die Ausdruckarten, die ich normalerweise verwende, nicht verwenden. – Kristoffer

Antwort

4

Wenn Sie GCC verwenden, sehen Sie -finstrument-functions Schalter - siehe https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html#index-finstrument-functions Er fordert im Grunde benutzerdefinierte Funktion beim Betreten und jede aufgerufene Funktion zu verlassen. Dies hat einige Vorteile:

  • Sie müssen Ihre Funktionen überhaupt nicht ändern. noch
  • Ihr Code egal genannt wird, wie die Funktion exitted (Sie können eine beliebige Anzahl von return in Ihrer Funktion haben und do not care)
+0

Das scheint in der Tat zu tun, was ich will! Jetzt ist das Problem, wie man irgendwie eindeutige Informationen erstellt, auf denen Funktion angerufen wurde, und tut es wirklich schnell. Semihosting ist leider viel zu langsam. Ich brauche Mikrosekundenauflösung und habe nicht viel Speicher übrig. – Kristoffer

+0

Die eindeutige Information, die Sie benötigen, ist das erste Argument des '__cyg_profile_func_enter()', das ein Zeiger ist, der die aufgerufene Funktion darstellt. Jetzt kommt es darauf an, was genau Sie in diesen Enter/Exit-Funktionen tun müssen. –

3

Sie können den Funktionsnamen anstelle einer Nummer als ID verwenden. da der Funktionsname eindeutig ist. zum Beispiel können Sie die Makros verwenden:

#define START printf("%s:%d Start \n", __func__, __LINE__) 
#define END printf("%s:%d End \n", __func__, __LINE__) 

oder im Kernel:

#define START pr_err(KBUILD_MODNAME ":%s:%d start \n", __func__, __LINE__) 
#define END pr_err(KBUILD_MODNAME ":%s:%d end\n", __func__, __LINE__) 
+0

Mehrere Dateien könnten jeweils eine separate 'static void Funktion (void) haben;' Funktion darin; Funktionsnamen sind nicht unbedingt in den Quelldateien eindeutig (obwohl ich denke, dass sie sich in einer einzigen Datei befinden - ich kann mir keine Möglichkeit vorstellen, diese Einschränkung zu umgehen). –

1

Es kann mehr beschreibend und nicht zu verwenden __FUNC__ als __COUNTER__. Hier ist eine Beispielimplementierung eines Makros, das das tut, was Sie wollen.

#include <stdio.h> 

#define WRAPPED_FUNC(funcname, ...) \ 
    funcname { \ 
     printf("Function %s entered\n", __func__); \ 
     __VA_ARGS__ \ 
     printf("Function %s exited\n", __func__); \ 
    } 

WRAPPED_FUNC(
    void helloWorld(), 
    { 
     printf("Hello World!\n"); 
    } 
) 

WRAPPED_FUNC(
    void worldHello(), 
    { 
     printf("World hello!\n"); 
    } 
) 

int main() { 
    helloWorld(); 
    worldHello(); 
    return 0; 
}