2017-12-07 9 views
1

Lassen Sie uns sagen, ich habePflanzgut Aufruf Kontext GCC Präprozessormakro Werte zu Zielfunktion

foo() { 
    bar(); 
} 

wo foo liegt in f.c und bar liegt in b.c, das heißt b.h in f.c enthalten ist. Ich möchte bar ändern zu drucken, dass sie von jeder Funktion aufgerufen wurde foo die sie aufruft, etwa so:

bar() { 
    printf ("Called from line %d in file %s",?,?); 
    /* Run as usual */ 
} 

ich diese zwei Stücke von Informationen aus dem predefined GCC preprocessor macros__LINE__ und __FILE__ erhalten möchten. Diese werden jedoch offensichtlich zu der Zeile printf in b.c und dem Pfad b.c jeweils ausgewertet, wenn sie einfach in die printf gesteckt werden.

Kann ich propagieren irgendwie die Werte von __LINE__ und __FILE__ vom rufenden Zusammenhang mit den printf in bar, so „von der Linie x in der Datei foo.c Called“ anstelle gedruckt?

ich versuchte bar zu bar2 umbenennen und dann eine Delegator-Funktion in der Datei-Header definieren b.h:

bar() { 
    printf ("Called from line %d in file %s",__LINE__,__FILE__); 
    bar2(); 
} 

Die Idee war, dass die #include Richtlinie den Header-Code in der Quelldatei f.c und dann würde kopieren ersetzen der Pfad zu f.c bzw. Zeilennummer. Dies gab mir jedoch einen doppelten Definitionsfehler über die verschiedenen Übersetzungseinheiten.

Als nächstes habe ich versucht, den static Modifizierer zu der Headerdefinition von bar2 hinzuzufügen, um mehrere Definitionen zu ermöglichen. Ich kann dann ohne Fehler kompilieren und das Programm ausführen, aber nur bar.h wird gedruckt.

Wohin gehe ich falsch? Ich bin sicher, dass es einen eleganteren Weg gibt, dies zu tun.

Fragen:

  1. Warum nicht einfach einen Debugger wie GDB benutzen? Dies ist ein Kernel-Code.

  2. Warum nicht auf der Anruferseite debuggen? Große Codebasis.

EDIT:

Warum funktioniert das nicht?

#ifdef DEBUG_PALLOC 
#define palloc_get_page(FLAGS) (palloc_get_page_debug (FLAGS, __FILE__,__LINE__)) 
#else 
void *palloc_get_page (enum palloc_flags); 
#endif 
+1

Sie müssen es als Parameter übergeben. OT: Weißt du was FAQ bedeutet? –

+0

Whoops, mein Schlechter. FAQ mit Fragen ersetzt Danke für die Antwort. Kannst du mir sagen, warum das nicht möglich ist? Kann ich nicht überall lokale Definitionen der Funktion haben, die nach dem Drucken auf globale Symbole zeigen? –

Antwort

3

könnten Sie einen Delegaten, aber nicht eine Funktion in der .h als __FILE__ und __LINE__ im .h sein würde (und die static Modifikator helfen hier nicht), aber mit einem Makro welche expandieren an der richtigen Stelle mit der richtigen Datei & Zeile Info.

void bar(const char *file, int line) 
{ 
    printf ("Called from line %d in file %s",line,file); 
} 

Die GDB Methode ist komplexer:

#define bar2() bar(__FILE__,__LINE__) 

und bar sollte Datei & Zeilenparameter akzeptieren. Das könnte funktionieren mit:

  • einem gdb-Skript, das die aktuellen Breakpoint-Position/Zurückverfolgungs druckt und fährt fort:
  • eine Zusammenarbeit bar Funktion, die einen Haltepunkt auslöst (auf Intel/Windows mit der Breakpoint Funktion oder asm("int $3") Richtlinie, ., wenn ein Flag/env var gesetzt ist zu sagen, dass der Debugger aktiviert ist, aber wenn bar oft genannt wird, könnte dies das Programm viel)

Hinweis verlangsamen: wenn Sie wollen es aktivierbare machen oder nicht, Dies wird komplexer, aber durch das Setzen einer Befehlszeile -DDEBUG Flagge können Sie die folgenden Druck machen die Linien oder nicht:

Datei bar.h:

#pragma once 
#ifdef DEBUG 

#define bar2() bar(__FILE__,__LINE__) 
void bar(const char *file, int line); 

#else 
void bar2(); 
#endif 

Datei bar.c

#include "bar.h" 
#include <stdio.h> 

#ifdef DEBUG 
void bar(const char *file, int line) 
#else 
void bar2() 
#endif 

{ 
#ifdef DEBUG 
    printf ("Called from line %d in file %s\n",line,file); 
#endif 
    printf("NOP\n"); 
} 

Anruf bar2 von Ihrem Hauptprogramm. Wenn DEBUG festgelegt ist, ist bar2 ein Makro, das bar aufruft. Wenn DEBUG nicht eingestellt ist, ist bar2 direkt Ihre Funktion.

Beachten Sie, dass dies für alle Ihre Funktionen mühsam ist, es sei denn, Sie verwenden ein Skript, um diese Muster zu generieren.

+0

Super! Werde dies so schnell wie möglich versuchen. Aus pädagogischen Gründen funktioniert die Verwendung des Begriffs "static", um mehrere Definitionen zuzulassen, hier jedoch nicht. –

+0

nicht aus dem gleichen Grund: '__FILE__' und' __LINE__' beziehen sich auf die Originaldatei, aus der sie enthalten sind. Nur Makros können diese Dynamik erzeugen. –

+0

ja, definiere nur das Makro, aber definiere den Funktionsprototyp danach nicht, da er sich ausdehnt –

Verwandte Themen