Multiple Definition (zwecks zwei *.cpp Dateien)



  • Abend,

    nochmals ich. Das Problem hatte ich jetzt schon ofter, habs aber bislang noch nicht so richtig gechecket (die Abhilfe).

    Folgendes: Mein Code hat eine Main.cpp und bislang zwei Klassen. Zum Kompilieren habe ich folgende CMD:

    make
    g++ -g -Wall -Wextra -pedantic-errors -std=c++11 -I/home/shorty/OpenFOAM/development/flameletcreator/src/chemistry -I/home/shorty/OpenFOAM/development/flameletcreator/src/typedef -o automaticFlameletCreator automaticFlameletCreator.cpp chemistry/chemistry.cpp chemistry/chemistryReader.cpp
    

    Wie man deutlich sieht, habe ich 3 *.cpp Dateien. Zwei davon greifen auf die typedef.hpp zu und daher bekomme ich den Fehler das ich multiple definition habe:

    /tmp/ccUIyN8D.o: (.rodata+0x8): multiple definition of `AFC::Info'
    /tmp/ccAs4DJ4.o: (.rodata+0x8): first defined here
    /tmp/ccUIyN8D.o: (.rodata+0x10): multiple definition of `AFC::Error'
    /tmp/ccAs4DJ4.o: (.rodata+0x10): first defined here
    /tmp/ccUIyN8D.o: (.rodata+0x18): multiple definition of `AFC::endl'
    /tmp/ccAs4DJ4.o: (.rodata+0x18): first defined here
    /tmp/cc24I0we.o: (.rodata+0x8): multiple definition of `AFC::Info'
    /tmp/ccAs4DJ4.o: (.rodata+0x8): first defined here
    /tmp/cc24I0we.o: (.rodata+0x10): multiple definition of `AFC::Error'
    /tmp/ccAs4DJ4.o: (.rodata+0x10): first defined here
    /tmp/cc24I0we.o: (.rodata+0x18): multiple definition of `AFC::endl'
    /tmp/ccAs4DJ4.o: (.rodata+0x18): first defined here
    

    Leider weiß ich nicht wie die Abhilfe aussieht. Habs mal mit statischen Libraries probiert (also für Chemistry und ChemistryReader eine Lib erstellt und diese beim Kompilieren mit der Main.cpp gelinkt, gleicher Fehler).

    g++ -static automaticFlameletCreator.cpp -L. -lChemistry -lChemistryReader -o statically_linked -I/home/shorty/OpenFOAM/development/flameletcreator/src/chemistry -I/home/shorty/OpenFOAM/development/flameletcreator/src/typedef
    

    Für nen Tipp wäre ich dankbar und sorry für den 3ten Thread heute.
    Ich sollte vllt auch einfach ins Bett (die klassische Ausrede für Unwissenheit 😉 )

    Grüße Tobi



  • Deine Funktionen nicht in der typedef.hpp definieren sondern in einer entsprechenden cpp Datei. In den Header gehört nur die Deklaration.



  • Schreib einfach ein inline vor die Funktionen.



  • Hallo und danke für die Rückmeldung. Die Problemzeilen sind Referenzen. Hier die typedef.hpp:

    #ifndef TYPEDEF_HPP
    #define TYPEDEF_HPP
    
    #include <vector>
    #include <string>
    #include <string.h>
    #include <iostream>
    
    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
    
    namespace AFC
    {
    
    /*---------------------------------------------------------------------------*\
                              AFC Defintions and typedef
    \*---------------------------------------------------------------------------*/
    
    //typedef std::cout Info;
    
    typedef double scalar;
    
    typedef std::vector<double> scalarField;
    
    typedef std::string string;
    
    typedef std::vector<string> stringField;
    
    #define forAll (tmp, i) for (unsigned int i=0; i<(tmp).size(); i++);
    
    std::ostream& Info = std::cout;
    
    std::ostream& Error = std::cerr;
    
    std::basic_ostream<char>& (&endl)(std::basic_ostream<char>&) = std::endl;
    
    inline void FatalError
    (
        const string msg,
        const char *file,
        const unsigned long line
    )
    {
        Error<< "\n";
        Error<< "Error in " << file << " line " << line << endl;
        Error<< msg << "\n" << endl;
    }
    
    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
    
    } // End namespace AFC
    
    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
    
    #endif // TYPEDEF_HPP_INCLUDED
    
    // ************************************************************************* //
    

    Via static kann ich das Problem beheben (kam mir gerade).



  • Static lässt zwar die Meldungen verschwiedenen, du hast dann aber mehrere Variablen.



  • manni66 schrieb:

    Static lässt zwar die Meldungen verschwiedenen, du hast dann aber mehrere Variablen.

    Stimmt und das für jede C++ Datei, die diese typedef.hpp einbindet. Ist also noch nicht die optimale Lösung. Weiß allerdings gerade nicht wie ich das Problem anders umgehen könnte. Ne Funktion ist es ja nicht, deswegen geht inline nicht. Definition in einer C++ Datei macht mir gerade Probleme. Die Deklaration der Header sieht gerade wie folgt aus:

    std::ostream& Info;
    std::ostream& Error;
    

    Beim kompilieren (ohne c++ Datei) bekomm ich die übliche Meldung, deklariert als Referenz aber nicht initialisiert. Mir ist jedoch gerade unklar wie ich die Definition in der c++ Datei erstelle. Ein Beispiel:

    std::ostream& AFC::Info = std::cout;
    

    Hier kommt (ist auch offensichtlich) folgende Meldung:

    typedef/typedef.hpp:58:15: error: 'std::ostream& AFC::Info' previously declared here
     std::ostream& Info;
    

    Kritik erwünscht.
    Danke schonmal.

    Grüße Tobi



  • Shor-ty schrieb:

    Wie man deutlich sieht, habe ich 3 *.cpp Dateien. Zwei davon greifen auf die typedef.hpp zu und daher bekomme ich den Fehler das ich multiple definition habe:

    Nur nochmal zur Klarstellung: Jede cpp wird komplett einzeln behandelt. Wenn die naechste cpp kompiliert wird, hat der Compiler komplett vergessen, was in der cpp davor war. Allerdings wird alles was includiert wird, komplett in die cpp eingefuegt (durch den Praeprocessor) bevor der Compiler die cpp sieht. Dinge die in Headern stehen werden also potentiell mehrmals durch den Compiler abgearbeitet. Ist dort z.b. eine Variable drin, so existiert diese Variable mehrfach. Ist so eine Variable nach aussen sichtbar, ist der Name am Ende nicht mehr eindeutig. Daher legt man in einem Header normalerweise nie eine Variable an. Normalerweise behauptet man einfach nur gegenueber dem Compiler, das eine Variable in irgendeiner cpp exisitiert und der Linker sie spaeter finden wird. Das nennt man dann Deklaration.



  • Hi TGGC,

    danke für deine ausführliche Antwort. Ist immer schön wenn mans auf verschiedene Art und Weisen zu hören bekommt. Das mit der Deklaration und Definition sollte mir eigentlich bekannt sein. Hab die Variablen jetzt in der Header deklariert und in der C++ definiert. Das Problem war, dass ich die Variable in der Header nicht als "extern" deklariert habe. Somit hat er in der C++ Datei immer gemeckert.

    Damit klappt es:

    Header:

    namespace AFC
    {
        extern std::ostream& Info;
        extern std::ostream& Error;
    }
    

    C++:

    std::ostream& AFC::Info = std::cout;
    std::ostream& AFC::Error = std::cerr;
    

    Grüße Tobi


Log in to reply