2008-10-30 2 views
32

Ich habe eine Header-Datei x.h, die von mehreren * .c Quelldateien enthalten ist. In dieser Headerdatei sind einige Strukturvariablen definiert.Warum verhindern meine Compile-Wachen keine Mehrfachdefinitionseinschlüsse?

Ich habe mehrere Inklusion Prävention Wache am Anfang der Header-Datei setzen, wie:

#ifndef X_H 
#define X_H 
... 
.. 
//header file declarations and definitons. 


#endif//X_H 

Auf Gebäude erhalte ich Fehler Linker an mehreren Definitionen zusammen. Ich verstehe das Problem.

  1. Wird nicht ein Mehrfaches Wache Inklusion Prävention an der Spitze der Header-Datei, wie ich, mehrere Einschlüsse der x.h Header-Datei verhindern und dadurch mehrere Definitionen der Variablen zu vermeiden, gibt es in x.h?

  2. #pragma einmal funktioniert nicht auf diesem bestimmten Compiler, also was ist die Lösung? Jemand hatte gepostet this Antwort auf eine ähnliche Frage. Es scheint nicht für mich zu funktionieren. Wie funktioniert diese Lösung?

+1

@Stephen: Wenn Sie bereits den Fragetitel bearbeiten, sehen Sie sich bitte auch den Körper an (und vielleicht Tags, wenn auch nicht hier). Dies vermeidet doppelte Bearbeitung (und Stoßen). –

+0

@Paulo Ich habe es verpasst, aber ich habe versucht, darauf zu achten, danke für die Erinnerung! – Stephen

Antwort

2

eine multiple Inklusion guard Verwendung verhindert Compiler Fehler, aber Sie sind ein Linker-Fehler. Haben Sie Datendefinitionen in der Headerdatei, die extern nicht verwenden?

9

Die Verwendung von Include-Wächtern verhindert, dass eine Kompilierungseinheit den Header zweimal enthält. Z.B. Wenn Header B.h A.h enthält und B.cpp A.h und B.h enthält, wird alles von A.h zweimal in der Kompilation B.cpp deklariert, wenn Sie keine Include-Wächter verwenden.

Ihre Include-Wachen verhindern das, bis jetzt ist alles in Ordnung.

Aber Sie erhalten mehrere Definitionen zur Verknüpfungszeit, dh zwei Kompilierungseinheiten definieren dasselbe. Dies bedeutet wahrscheinlich, dass Sie eine echte Definition in Ihrer Kopfzeile haben, extern für alle Variablen verwenden, sicherstellen, dass Funktionen entweder inline oder definiert sind die CPP-Datei.

35

Wenn der Linker sich beschweren, bedeutet dies, dass Sie Definitionen und nicht nur Deklarationen in Ihrem Header haben. Hier ist ein Beispiel für Dinge, die falsch wären.

#ifndef X_H 
#define X_H 

int myFunc() 
{ 
    return 42; // Wrong! definition in header. 
} 

int myVar; // Wrong! definition in header. 

#endif 

Sie sollten diese aufgeteilt in Quelle und Header-Datei wie folgt aus:

Rubrik:

#ifndef X_H 
#define X_H 

extern int myFunc(); 

extern int myVar; 

#endif 

C Quelle:

int myFunc() 
{ 
    return 42; 
} 

int myVar; 
+0

Die 'int myVar;' ist höchstens eine vorläufige Definition; Es verursacht normalerweise keine Probleme. Wenn es einen Initialisierer gäbe, würde es. Dennoch verwende ich immer ein explizites Extern, wie du es in der 'fixierten' Version zeigst. –

+0

@ Jonathan: Gibt es so etwas wie eine "vorläufige Definition" in der C-Norm? Ich denke, was passiert ist, dass mehrere Definitionen wie diese "undefined Verhalten" verursachen, aber in vielen Compilern/Linkern (GCC ...), ist das Verhalten, das Sie erhalten, was Sie wollen! – Roddy

+0

wäre es möglich, eine Inline-Deklaration einer Funktion zu haben, auf die sofort ihre Definition folgt? –

4

Wenn die Funktionen nicht groß sind, Sie können "inline" vor ihnen verwenden und der Linker wird sich nicht beschweren.

7

Header-Wächter eignen sich nur für eine einzelne Kompilierungseinheit, d. H. Quelldatei. Wenn Sie eine Header-Datei mehrere Male enthalten, vielleicht, weil alle Header von main.c wiederum stdio.h enthalten sind, dann werden Wächter helfen.

Wenn Sie die Definition einer Funktion f in x.h haben, die durch main.c und util.c enthalten ist, dann ist es wie das Kopieren und Einfügen der Definition von f in main.c wenn main.o zu schaffen und tun das gleiche für util.cutil.o zu erstellen. Dann wird sich der Linker beschweren und das passiert trotz deiner Kopfwachen. Aufgrund dieser Wächter ist natürlich eine #include "x.h" Erklärung in main.c möglich.

+0

Ich hatte diesen Zweifel seit langer Zeit! Deine Erklärung löscht es :-) – Shailesh

0

Vielleicht ist X_H bereits wo anders definiert? Ich bin gerade auf dieses Problem gestoßen, wo Xlib X_H in /usr/include/X11/X.h definiert.

Um zu überprüfen, können Sie gcc -dM -E aufrufen (wenn Sie gcc verwenden), z. in dem Buildsystem, das ich verwende, funktioniert das mit CC=gcc CFLAGS="-dM -E" make. Wenn die Ausgabedatei #define X_H enthält, obwohl Sie sie aus Ihrer Datei entfernen (z. B. Y_H), ist sie bereits außerhalb Ihres Quellcodes definiert.