Registrierung jede C / C ++ Quelldatei eine Runtime-Liste der aktuell verfügbaren Quellen zu erstellen

StackOverflow https://stackoverflow.com/questions/618581

Frage

Für eine Debugging und Logging-Bibliothek, die ich will, zu finden in der Lage sein zur Laufzeit, eine Liste aller von den Quelldateien, die das Projekt kompiliert und verknüpft werden. Ich nehme an, ich von Header einschließlich irgendeiner Art in jeder Quelldatei sein werden, und der Präprozessor __FILE__ Makro kann mich konstant ein Zeichen für diese Datei geben, so muss ich nur irgendwie „ausgestrahlt“, dass die Informationen aus jeder Datei durch ein gesammelt werden Laufzeitfunktion.

Die Frage ist, wie elegant, dies zu tun, und vor allem, wenn es von C zu C ++ im Gegensatz getan werden kann. In C ++ würde ich wahrscheinlich versuchen, eine Klasse mit einem statischen Speicher, um die Liste der Dateinamen zu halten. Jeder Header-Datei würde eine Datei-lokale statische Instanz dieser Klasse erstellen, die bei der Erstellung der Dateizeiger oder was auch immer in der Klasse des statischen Datenelemente anhängen würde, vielleicht als eine verknüpfte Liste.

Aber ich glaube nicht, das in C arbeiten, und auch in C ++ Ich bin nicht sicher, es ist garantiert, dass jedes Element erstellt wird.

War es hilfreich?

Lösung

Ich würde so etwas direkt im Code nicht tun. Ich würde ein Tool schreiben, die die Projektdatei analysiert (vcproj, Make-Datei oder auch nur scannen das Projektverzeichnis für * .c * Dateien) und erzeugen eine zusätzliche C-Quelldatei, die die Namen aller Quelldateien in einer Art prä- enthielt initialisierte Datenstruktur.

Ich würde dann dieses Werkzeug Teil des Build-Prozesses machen, so dass jedes Mal, wenn Sie einen Build tun all dies automatisch geschehen würde. Zur Laufzeit alles, was Sie zu tun haben würden, ist, dass Datenstruktur lesen, die gebaut wurde.

Andere Tipps

Ich stimme mit Ferruccio, der beste Weg, dies ist im Build-System zu tun, nicht der Code selbst. Als Erweiterung seiner Idee, fügen Sie ein Ziel zu Ihrem Build-System, das eine Liste der Dateien Dumps auf eine C-Datei als String (die es ohnehin wissen muss), oder ein Array von Strings, und diese Datei in Ihre Quelle kompiliert. Dies vermeidet eine Menge Komplikation in der Quelle und ist erweiterbar, wenn Sie zusätzliche Informationen hinzufügen mögen, wie die Versionsnummer von Ihrem Quellcodeverwaltungssystem, der die ausführbare Datei erstellt, etc.

Es ist eine Standardmethode unter UNIX und Linux - ident. Für jede Quelldatei erstellen Sie ID-Tag - in der Regel durch Sie Versionskontrollsystem zugeordnet ist, z.B. SVN keywords .

Dann den Namen und die Revision jeder Quelldatei, um herauszufinden, die Sie gerade ident Befehl verwenden. Wenn Sie es zur Laufzeit tun, müssen überprüfen, wie ident es tut -. Quelle für sie frei verfügbar sein sollten

Theres keine Möglichkeit, es in C. In C ++ tun Sie eine Klasse wie folgt zu erstellen:

struct Reg {
   Reg( const char * file ) {
      StaticDictionary::Register( file );
};

wo StaticDictionary ist ein Singleton Container für alle Dateinamen. Dann in jeder Quelldatei:

static Reg regthisfile( __FILE__ );

Sie würden wollen, um das Wörterbuch machen a Meyers Singletons Schöpfungsordnung Probleme zu vermeiden.

Ich glaube nicht, dass Sie dies in der Art und Weise tun, können Sie in einem „passiven“ Modus skizzieren. Das heißt, Sie gehen irgendwie Code ausführen für jede Quelldatei in der Registrierung hinzugefügt werden, ist es schwer zu bekommen es automatisch geschehen.

Natürlich ist es möglich, dass Sie, dass Code mit Hilfe von Makros sehr unauffällig machen. Es könnte für C-Quelldateien problematisch sein, die keinen „Einstiegspunkt“ haben, also, wenn Ihr Code wird als „Module“ nicht bereits organisiert, mit z.B. eine init() Funktion für jedes Modul, könnte es schwierig sein. Statische Initialisierung Code könnte möglich sein, ich bin nicht 100% sicher, ob die Reihenfolge, in der die Dinge initialisiert werden hier Probleme schafft.

static Speicherung in dem Registry-Modul verwenden klingt wie eine gute Idee, eine einfache verknüpfte Liste oder einfache Hash-Tabelle sollte einfach genug sein, um zu implementieren, wenn das Projekt nicht enthält bereits all Allzweck-Utility-Bibliothek.

In C ++ Ihre Lösung funktionieren wird. Es ist garantiert.

Edit: Nur eine Lösung in meinem Kopf herausgefunden: eine Regel in Ihrer Make-Datei ändern hinzufügen '-Include "cfiles_register.h"' zu jedem 'g ++ file.cpp'.

%.o : %.cpp
    $(CC) -include 'cfiles_register.h' -o $@ $<

setzen Sie Ihre in der Frage implemnatation zu diesem 'cfiles_register.h' vorgeschlagen.

Die Verwendung von statischen Instanzen in C ++ in Ordnung funktionieren würde.

Sie können dies tun, auch in C, aber Sie müssen Runtime-spezifische Funktionen nutzen - für MSVC CRT einen Blick auf http://www.codeguru.com/cpp/misc/misc/threadsprocesses/article.php/c6945/

Für C - Sie kann es mit einem Makro tun könnten - definiert eine Variable Ihre Datei mit dem Namen entspricht, und dann könnte man die Symbole der ausführbaren Datei scannen, nur als eine Idee:

 #define TRACK_FILE(name) char _file_tracker_##name;

verwenden Sie es in Ihrem my_c_file.c wie folgt aus:

 TRACK_FILE(my_c_file_c)

und als grep alle Datei / Variablennamen aus dem binären wie folgt

nm my-binary | grep _file_tracker

Nicht wirklich schön, aber ...

Horrible Idee, ich bin sicher, aber ein Singleton verwenden. Und auf jede Datei so etwas wie

  Singleton.register(__FILE__); 

im globalen Bereich. Es wird nur wenn auf CPP-Dateien. Ich habe so etwas wie dies schon vor Jahren als Novize, und es funktionierte. Aber ich würde zurückschrecken, es jetzt zu tun. Ich würde jetzt einen Build-Schritt hinzuzufügen.

ich mit denjenigen überein, die sagen, dass es besser ist, dies zu tun während der Laufzeit zu vermeiden, aber in C können Sie eine statische Variable mit einem Funktionsaufruf initialisiert werden, das heißt, in jeder Datei:

static int doesntmatter = register( __FILE__);
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top