a Bereits in b.obj definiert



  • Beim Linken meine Projekts (das ich nach 6 Monaten Unterbrechung wg. Abitur mal wieder fortführe) ergeben sich folgende Fehlermeldungen:

    video_info.obj : error LNK2005: "int  ERROR" (?ERROR@@3HA) bereits in main.obj definiert
    video_info.obj : error LNK2005: "int  SUCCESS" (?SUCCESS@@3HA) bereits in main.obj definiert
    timing.obj : error LNK2005: "int  ERROR" (?ERROR@@3HA) bereits in main.obj definiert
    timing.obj : error LNK2005: "int  SUCCESS" (?SUCCESS@@3HA) bereits in main.obj definiert
    sprites.obj : error LNK2005: "int  ERROR" (?ERROR@@3HA) bereits in main.obj definiert
    sprites.obj : error LNK2005: "int  SUCCESS" (?SUCCESS@@3HA) bereits in main.obj definiert
    stars.obj : error LNK2005: "int  ERROR" (?ERROR@@3HA) bereits in main.obj definiert
    stars.obj : error LNK2005: "int  SUCCESS" (?SUCCESS@@3HA) bereits in main.obj definiert
    Debug/Rocket.exe : fatal error LNK1169: Ein oder mehrere mehrfach definierte Symbole gefunden
    

    Zur Erklärung: Es gibt eine Datei main.cpp, die u.a. constants.h einbindet und die zu den oben aufgeführten Objektdateien gehörenden .cpp-Dateien, die auch jeweils constants.h einbinden. Alle Header-Dateien sind aber mit #ifndef vor Mehrfacheinbindung geschützt.

    Wieso gibt es dann diese Fehler?



  • einfach alle .obj dateien löschen und neu compilieren



  • Poste mal in Inhalt von Constants.h...



  • Hier also der Inhalt von constants.h:

    #ifndef CONSTANTS_H
    #define CONSTANTS_H
    
    //-----------------------------------------------
    // SDL and SDL libs header
    //-----------------------------------------------
    
    #include "SDL.h"
    
    //-----------------------------------------------
    // user defined data types
    //-----------------------------------------------
    
    struct Point
    {
        double x;
        double y;
    };
    
    //-----------------------------------------------
    // shortcuts and alias names
    //-----------------------------------------------   
    
    #define             SCREEN SDL_GetVideoSurface() 
    
    #define             UCHAR   unsigned char
    #define             USHORT  unsigned short
    #define             UINT    unsigned int
    #define             ULONG   unsigned long
    
    const unsigned      GAME_WINDOW = SDL_HWSURFACE | SDL_DOUBLEBUF;
    
    int                 SUCCESS = 0;
    int                 ERROR = -1;
    
    // colors
    
    const SDL_Color black   = {0  ,  0  ,0};
    const SDL_Color white   = {255,255,255};
    const SDL_Color yellow  = {255,255,  0};
    const SDL_Color purble  = {255,  0,255};
    const SDL_Color cyan    = {0,  255,255};
    const SDL_Color red     = {255,  0,  0};
    const SDL_Color green   = {  0,255,  0};
    const SDL_Color blue    = {  0,  0,255};
    
    // video info
    
    enum VideoInfo {    video_driver_name   =   0, 
    hw_available        =   1,
    wm_available        =   2,
    blit_hw             =   3,
    blit_hw_CC          =   4,
    blit_hw_A           =   5,
    blit_hw_sw          =   6,
    blit_sw_CC          =   7,
    blit_sw_A           =   8,
    blit_fill           =   9,
    video_mem           =  10};
    
    enum TimerState { timerIdle, timerRunning, timerDone};
    
    #endif
    

    P.S. das Löschen der Objektdateien und das anschließende Neucompilieren hat nichts verändert.



  • du verletzt die ODR (one definition rule)



  • @ Shade

    Wieso? ERROR und SUCCESS sind nur ein einziges Mal definiert und zwar in constants.h, d.h. wie in dem Listing was ich oben gepostet habe.
    Ich habe schon alle anderen Quellcodedateien nach weiteren Definitionen von ERROR und SUCCESS durchsucht, doch ohne Erfolg, d.h. beide sind wirklich nur ein einzige Mal definiert.



  • Original erstellt von heute_heiße_ich_SMax:
    Wieso? ERROR und SUCCESS sind nur ein einziges Mal definiert und zwar in constants.h

    Einen Linkerfehler erhält, wer ein Objekt mehrfach definiet. Dies passiert am Ehesten, wenn man einen Header, der Objekte definiert, in zwei oder mehr cpp-Dateien einbindet.

    lies Humes text bitte nochmal und achte speziell auf den untersten source code!



  • Wieso? ERROR und SUCCESS sind nur ein einziges Mal definiert und zwar in constants.h, d.h. wie in dem Listing was ich oben gepostet habe.

    Nö. Der Preprozessor macht quais copy and paste. Das heißt es ist einmal in deiner main.cpp und einmal in jeder anderen Datei definiert, die constants.h einbinden. Versuch mal ein extern in constants.h vor die definition zu stellen (also eine deklaration draus zu machen) und eine weitere Datei mitzulinken, in der die Variablen definiert werden (z.B. constants.cpp).



  • Aber durch das #ifndef CONSTANTS_H kann doch constants.h nicht mehrfach eingebunden werden, sodass es - für den Fall das ERROR und SUCCESS wirklich nur einmal, nämlich in constants.h definiert sind - keine Mehrfacheinbindung geben dürfte.



  • const int SUCCESS = 0;
    const int ERROR = -1;



  • Durch die #include-Guards erreichst du nur, dass derselbe Header nicht mehrfach in eine Quellcodedatei eingebunden wird, z.B. durch gegenseitige #includes der Headerdateien untereinander.



  • @ ERROR_SUCCESS

    Danke, jetzt funktionert es. Aber wieso?



  • Original erstellt von Heute_heiße_ich_smax:
    Danke, jetzt funktionert es. Aber wieso?

    lies mal den Text von Hume!!

    da steht doch ganz eindeutig, dass die ODR verletzt wird, wenn du eine variable in mehreren ÜEs definierst.

    wenn du jetzt auch noch weißt was #include macht, dann sollte es klar sein.

    erklär mir mal:

    Was ist eine ÜE?
    Was macht #include?

    wenn du jetzt
    ÜE 1 hast:

    #include "constant.h"
    ...

    und in ÜE 2 dann:

    #include "contant.h"
    ...

    welchen code bekommt dann der compiler?
    (include wird ja bekanntlich vom preprozessor ersetzt)

    warum const int geht steht auch in Humes Text, bitte lies ihn!!



  • Außerdem ist es doch auch logisch, dass wenn du Konstanten haben willst, auch const davor schreiben solltest. 😉



  • @ ++

    Ja, das kann ich nachvollziehen 😃

    @ Shade

    Die one defintion rule (ODR) besagt, dass in einem Programm für jede Variable, jede Funktion, jede Klasse, jede Aufzählung und jedes Template nur genau eine Definition existieren darf.

    D.h. wenn man aus den Variablen SUCCESS und ERROR durch const Konstanten macht, dann wird die ODR nicht verletzt, weil für Konstanten mehrere Definitionen existieren dürfen (sorry, war gestern etwas schläfrig).



  • D.h. wenn man aus den Variablen SUCCESS und ERROR durch const Konstanten macht, dann wird die ODR nicht verletzt

    Richtig.

    weil für Konstanten mehrere Definitionen existieren dürfen (sorry, war gestern etwas schläfrig).

    Für Integer-Konstanten wird in der Regel überhaupt kein eigener Speicher angelegt.
    Außerdem gilt:
    a) "normale" Konstanten sind implizit static, haben also internal linkage. Demzufolge darf es eine Definition pro Übersetzungseinheit geben.

    b) extern deklarierte Konstanten dürfen nur *genau eine* Definition haben. Solange nur die Deklaration (extern const int bla;) im Header, die Definiton aber nur in *genau einer* cpp-Datei auftaucht ist alles ok.