Probleme mit Verständniss zum linker



  • Hallo zusammen,

    ich lerne nun seit ca. 3 Monaten C++. Als Lernhilfe habe ich "Thinking in C++, Vol 1, 2nd Edition von Bruce Eckel" (hab es von vielen empfohlen bekommen.

    Mittlerweile habe ich viele Dinge verstanden und kann kleine "dummy Programme" ohne Probleme Schreiben. Nun habe ich aber ein Problem mit einem Test-Projekt (finde, learning by doing ist immer noch das beste).

    Ich habe den Code auf mehrer Dateien verteilt. Folgende Dateien sind relevant:
    main.cpp
    classes/config.cpp
    classes/config.h
    classes/logger.cpp
    classes/logger.h

    In classes/config.cpp und classes/logger.cpp werden Klassen gebaut. In der main.cpp mache ich dann folgendes:

    loglib logger;
    cfglib config("example.conf");
    

    In der Klasse cfglib möchte ich aber auch gerne Log-Einträge erzeugen. Also habe ich in der classes/logger.cpp folgendes eingebaut:

    extern loglib logger;
    

    Ich habe mir ein Makefile gebastelt, dass so aussieht:

    INCLUDEPATH = . ./classes ./tools ./types
    LIBS = -L /usr/local/lib -lgcc -ldl -L ./yac.o
    CC = g++
    CCFLAGS =
    
    all: chat
    
    clean:
    	find . -name \*.so | xargs rm -f
    	find . -name \*.o | xargs rm -f
    	rm -f ./yac
    
    chat: ./classes/server.o ./classes/http.o ./classes/dso.o ./tools/signals.o ./classes/config.o ./classes/logger.o ./yac.o
    	$(CC) -o yac $+ $(LIBS)
    
    ./yac.o:
    	$(CC) -c ./yac.cpp -o ./yac.o
    
    ./classes/dso.o:
    	$(CC) -c ./classes/dso.cpp -o ./classes/dso.o
    
    ./classes/http.o:
    	$(CC) -c ./classes/http.cpp -o ./classes/http.o
    
    ./classes/server.o: ./classes/dso.o
    	$(CC) -c ./classes/server.cpp -o ./classes/server.o
    
    ./classes/config.o:
    	$(CC) -c ./classes/config.cpp -o ./classes/config.o
    
    ./classes/logger.o:
    	$(CC) -c ./classes/logger.cpp -o ./classes/logger.o
    
    ./tools/signals.o:
    	$(CC) -c ./tools/signals.cpp -o ./tools/signals.o
    

    Wenn ich dieses nun laufen lasse, werden die Objekt-Dateien auch alle ohne Fehler erstellt. Aber beim zusammenführen aller zum Binary bekomme ich folgenden Fehler raus:

    classes/config.o: In function `cfglib::load()':
    config.cpp:(.text+0x77): undefined reference to `logger'
    collect2: ld returned 1 exit status
    make: *** [chat] Fehler 1
    

    Ich muss gestehen, dass ich nicht genau weiß, was das Makefile macht. Ich habe mir den Aufbau aus verschiedenen Makefiles "zusammen gereimt". Leider sagt mir das Buch nicht viel, wie ich so etwas lösen kann sondern nur, dass die Reihenfolge sehr wichtig sein kann. google ist sehr geschwätzig. Wenn ich nach "undefined reference" suche, bekomme ich rund 17.000.000 Ergebnisse, wobei die sich fast alle um Probleme beim kompilieren von fertigen Sources handeln.

    Ich hoffte jemand von euch kann mir weiter helfen. Vielleicht einen Tipp wie mehr zu diesem Thema erfahren kann?

    Gruß,
    FunnyDingo



  • Der Linker bekommt die einzelnen .O Files vorgesetzt und baut daraus dann eine ausführbare Datei. Dazu sucht er zu allen (reinen) Deklarationen, die der Compiler gefunden hat (Funktions-Prototypen und extern-Variablen), die passende Definition (Funktionsrumpf bzw. Variablen-Definition) und ersetzt alle Verweise darauf durch die zugehörige Adresse. Wenn er allerdings keine Definition findet, hast du ein Problem - das äußert sich in der angegebenen Fehlermeldung.

    Zur Lösung: "extern" wird in einem Header verwendet, wenn die Variable von jedem genutzt werden soll, aber nur einmal existiert - da benötigst du in EINEM CPP die passende Definition. In deinem Fall heißt das: du brauchst den Eintrag "extern loglib logger;" in der logger.h und ein "loglib logger;" in der logger.cpp.

    PS: Das C++ Board ist übrigens nebenan 😉



  • Danke, das hat funktioniert. Irgendwie habe ich dass mit dem extern wohl missverstanden oder nicht ganz verstanden - sollte ich mir vielleicht noch mal ansehen.


Anmelden zum Antworten