Linkerprobleme bei Dev-C++
-
Hi Leute, hab ein merkwürdiges Problem:
Ich programmier an meinem Programm vor mich hin und compiliere mal und es funktioniert. Dann will ich es einen Moment später nochmal compilieren und es geht nich mehr. Darauf hin hab ich die paar Änderungen zurückgenommen und es wieder versucht aber: es geht nich oO. Ich benutz Dev-Cpp mit dem Allegro und AllegroFont-Paket.
Der Linker gibt mir aus: "undefined reference". Allerdings nich in meinem Programm, sondern irgendwo im AllegroFont Paket. von den undef. Referenzen zeigt er mir ne ganze Liste bis nur noch dasteht:
"alfont.c C:\Dev-Cpp\lib\libalfont.a(alfont.o)(.text+0x138c) more undefined references to `_imp__ugetxc' follow "Die Linkeroptionen sind wie eh und je. Hab Dev-Cpp und die Pakete in einem neuen Projekt ausprobiert und es geht alles. Nur in meinem Projekt eben nich. Auch nich, wenn ich alle Quelltexte in ein neues Projekt übernehme.
Ich versteh das nicht. Ich hab keine Ahnung woran es liegen könnte bzw. was ich machen könnte, um den Fehler zu finden. Hat einer ne helfende Idee?
mfg Marcel
-
Also wenn du dir absolut sicher bist, dass du nicht an den Compile- oder Linkereinstellungen rumgefrickelt hast:
Oft spinnt Dev-C++ einfach grundlos. Erstell ein neues Projekt mit den selben Einstellungen und uebernimm die Source-Files, das hilft meistens. (Alternativ: wechsle von Dev-C++ auf Code::Blocks (www.codeblocks.org), das hat wesentlich weniger solcher lustigen Ueberraschungen und wird auch noch aktiv weiterentwickelt, Dev-C++ hingegen ist ein totes Projekt)
-
Ich hab jetzt CodeBlocks ausprobiert (ein Hoch auf den "DevC++-Projekt importieren Schalter
). Wenigstens bekomme ich hier klare, aber genauso ungewöhnliche Fehlermeldungen (ebenfalls im Allegro-Paket).
Compiling: Ansicht.cpp
Compiling: Beschreibung.cpp
In file included from C:/Programme/CodeBlocks/include/allegro/3d.h:23,
from C:/Programme/CodeBlocks/include/allegro/gfx.h:22,
from C:/Programme/CodeBlocks/include/allegro.h:38,
from Objekt.h:5,
from Ort.h:13,
from Level.h:13,
from Beschreibung.cpp:2:
C:/Programme/CodeBlocks/include/allegro/fixed.h:30: error:fixed' does not name a type C:/Programme/CodeBlocks/include/allegro/fixed.h:31: error:
fixed' does not name a type
In file included from C:/Programme/CodeBlocks/include/allegro/gfx.h:22,
from C:/Programme/CodeBlocks/include/allegro.h:38,
from Objekt.h:5,
from Ort.h:13,
from Level.h:13,
from Beschreibung.cpp:2:
C:/Programme/CodeBlocks/include/allegro/3d.h:33: error:fixed' does not name a type C:/Programme/CodeBlocks/include/allegro/3d.h:34: error:
fixed' does not name a type
C:/Programme/CodeBlocks/include/allegro/3d.h:73: error:fixed' has not been declared C:/Programme/CodeBlocks/include/allegro/3d.h:73: error:
fixed' has not been declared
C:/Programme/CodeBlocks/include/allegro/3d.h:73: error: ISO C++ forbids declaration ofmin_z' with no type C:/Programme/CodeBlocks/include/allegro/3d.h:73: error: ISO C++ forbids declaration of
max_z' with no typeusw.
Es muss also wohl doch an meinem Programm liegen, nur kann ich aus den Fehlerprotokollen nicht rauslesen, wo ich denn nun die Welt zum Einsturz gebracht habe...
-
Jetzt habe ich durch massives Auskommentieren mein Programm zurückgebaut und dabei folgendes festgestellt:
Wenn ich in meiner Header-Datei "Objekt.h" bzw. der Datei "Objekt.cpp" keine Allegro-Routinen benutze und allegro.h nur hier nicht einbinde, funktioniert alles andere super.
Sobald ich aber in "Objekt.h" die Datei "allegro.h" einbinde, zeigt er mir obiges Fehlerprotokoll an.
Wenn ich statt dessen die Datei nicht einbinde, aber die benutzten Routinen so deklariere:
//#include <allegro.h> class BITMAP; class PAL; extern BITMAP* load_bmp(char*,PAL*); extern void destroy_bitmap(BITMAP*);
So gibt er mir "undefined reference" zu genau diesen beiden Funktionen in der "Objekt.o" aus.
Woran kann das liegen?
-
Bindest du deine eigenen Header einfach oder mehrfach ein?
Wenn mehrfach, abfragen ob eingebunden und nur wenn nein, dann einbinden.MfG f.-th.
-
Ich hab jetzt um die Stelle herumprograsmmiert und kann erstmal weitermachen, aber das Problem lässt ja meiner Lerngier keine Ruhe ^^
Ja, das Problem ist, dass sich meine Header sogar gegenseitig einbinden, weil die Objekte keine eindeutige Hirarchie aufweisen, sondern miteinander interagieren müssen. Darum hab ich das so gelöst:
#ifndef KLASSE_JETZT_H #define KLASSE_JETZT_H // Hier die größeren Header. #include <cstdlib> #include <allegro.h> // eventuell. // Hier meine Header. class KlasseJetzt; #include "andereKlasseA.h" #include "andereKlasseB.h" //usw. .. class KlasseJetzt { //... // Zeiger auf andereKlasseA und andereKlasseB kommen vor. //... }; #endif
-
koril-k schrieb:
Ich hab jetzt um die Stelle herumprograsmmiert und kann erstmal weitermachen, aber das Problem lässt ja meiner Lerngier keine Ruhe ^^
Ja, das Problem ist, dass sich meine Header sogar gegenseitig einbinden, weil die Objekte keine eindeutige Hirarchie aufweisen, sondern miteinander interagieren müssen. Darum hab ich das so gelöst:
Ja, da hast du im Ernstfall ein Problem - der Präprozessor ist noch dümmer als der Compiler und führt nur simple Textersetzungen durch. Das bedeutet, nach seiner Arbeit hast du eine große Quelltext-Datei, die an den Compiler übergeben wird - und in der müssen alle Header in einer genau definierten Reihenfolge stehen. Bei wechselseitigen Abhängigkeiten endet das dann damit, daß die nötigen Deklarationen erst hinter der Position landen können, an der sie gebraucht werden.
Die beste Lösung dafür ist es wohl, Header-Abhängigkeiten zu minimieren - solange du nichts über die Größe oder Struktur der Klassen wissen mußt, kannst du die#include "AndereKlasse.H"
problemlos ersetzen durch eine Forward-Deklarationclass AndereKlasse;
(und idR brauchst du im Header nur den Namen - die Struktur wird erst im zugehörigen CPP benötigt).
-
Ich habe bereits versucht, in einer Klasse keine Inline-Funktionen aufzunehmen, die die Methoden anderer Klassen verwendet. Sprich: In meinen Klassen sind eigentlich nur Zeiger vom Typ anderer Klassen enthalten und alle weiterführenden Interaktionen habe ich in die zugehörigen cpp-Dateien ausgelagert.
Allerdings bewahrt mich das nicht davor, die Header anderer Klassen einzubinden. Ich habe bereits versucht über "class andereKlasse;" nicht unnötig viele Header einzubinden, aber gelegentlich stoße ich dann auf ein "field x has incomplete type" (wenn x ein element einer klasse vom typ einer anderen Klasse ist).
Da ich vor den includes anderer Klassen ja bereits "class jetzigeKlasse;" habe ich (eine einfache Textersetzung vorausgesetzt) doch im Prinzip immer eine Forward Deklaration durchgeführt.
-
Vieleicht hilkft es, einfach mal alle Headerköpfe aufzulisten. Eventuell fällt ja jemandem etwas auf. Dahinter folgt jeweils immer die Klassendeklaration und das #endif.
#ifndef AKTION_H #define AKTION_H #include <string> #include <list> #include <cstdlib> #include <iostream> using namespace std; class Aktion; #include "Level.h"
#ifndef ANSICHT_H #define ANSICHT_H #include <allegro.h> #include <alfont.h> #include <string> #include <iostream> #include <cmath> using namespace std; class Ansicht; #include "Ort.h" #include "Objekt.h"
#ifndef BESCHREIBUNG_H #define BESCHREIBUNG_H #include <string> #include <cstdlib> using namespace std; // Hier käme eigentlich #include "Level.h", aber merkwürdigerweise // funktioniert hier nur die Forward-Deklaration. class Level;
#ifndef LEVEL_H #define LEVEL_H #include <list> #include <cstdlib> #include <fstream> #include <iostream> using namespace std; class Level; #include "Ort.h" #include "Objekt.h" #include "ScriptFile.h"
#ifndef OBJEKT_H #define OBJEKT_H //#include <allegro.h> #include <list> #include <cstdlib> #include <string> using namespace std; class Objekt; #include "Aktion.h" #include "Level.h" #include "Ort.h" #include "Beschreibung.h"
#ifndef ORT_H #define ORT_H #include <list> #include <cstdlib> #include <string> using namespace std; class Ort; #include "Level.h" #include "Objekt.h" #include "Beschreibung.h"
#ifndef SCRIPT_FILE_H #define SCRIPT_FILE_H #include <fstream> #include <string> #include <vector> #include <iostream> #include <cstdlib> #include <sstream> using namespace std; class ScriptFile; #include "Level.h" #include "Aktion.h"
-
koril-k schrieb:
Ich habe bereits versucht, in einer Klasse keine Inline-Funktionen aufzunehmen, die die Methoden anderer Klassen verwendet. Sprich: In meinen Klassen sind eigentlich nur Zeiger vom Typ anderer Klassen enthalten und alle weiterführenden Interaktionen habe ich in die zugehörigen cpp-Dateien ausgelagert.
Allerdings bewahrt mich das nicht davor, die Header anderer Klassen einzubinden. Ich habe bereits versucht über "class andereKlasse;" nicht unnötig viele Header einzubinden, aber gelegentlich stoße ich dann auf ein "field x has incomplete type" (wenn x ein element einer klasse vom typ einer anderen Klasse ist).
Wie gesagt - wenn du die Größe oder Struktur der Klasse brauchst (das schließt die Definition von Membern ein), reicht eine Forward Deklaration nicht mehr aus.
PS: Und die Header-Köpfe reichen nicht aus, um deine möglichen Fehler zu diagnostizieren. Wenn da etwas Probleme macht, sind das die Abhängigkeiten der Klassen selber.
-
zeig uns mal die ersten 10 Zeilen deiner Level.h
MfG f.-th.
-
Die Datei ist noch nicht groß. Hier ist die Ganze:
#ifndef LEVEL_H #define LEVEL_H #include <list> #include <cstdlib> #include <fstream> #include <iostream> using namespace std; class Level; #include "Ort.h" #include "Objekt.h" #include "ScriptFile.h" class Level { private: list<Ort*> orte; list<Objekt*> objekte; public: // Konstruktoren. Level() {}; ~Level() {}; // Dateiverwaltung. bool addFromFile( const string& ); // Zugriffsmethoden. Ort& neuerOrt( const string& = "" ); int getOrtAnz() const { return orte.size(); }; Ort& getOrt( int nr ) const; int getOrtNr( const string& ) const; Objekt& neuesObjekt( const string& = "" ); Objekt& neuesObjekt( const string&, Ort& ); Objekt& neuesObjekt( const string&, Ort&, Ort& ); int getObjAnz() const { return objekte.size(); }; Objekt& getObjekt( int nr ) const; int getObjektNr( const string& ) const; }; #endif