C++ linking error with multiple definition on linux

15.1k views Asked by At

I am trying to compile a code and it’s getting a linking error with multiple definitions. Unfortunately, I am not able to fix it and any help would be appreciated.

I have following files: Header files: CEST.h; CEST_UI.h; GlobalVariable.h;
Source file: CEST.cpp; CEST_UI.cpp; GlobalVariable.cpp

All parameters, which are claimed to have multiple definitions, are defined in “GlobalVariable.h” and initialized in “GlobalVariable.cpp”.

I am including “GlobalVariable.h” twice: once in CEST.cpp and second time in CEST_UI.cpp.

I was thinking that the following guard in “GlobalVariable.h” would have protected me aginst multiple definition linking error:

# ifndef GLOBALVARIABLE_H
#define GLOBALVARIABLE_H
………….
………….
#endif

I am also attaching “GlobalVariable.h” and “GlobalVariable.cpp” so that you can have a look.

In “GlobalVariable.h”

# ifndef GLOBALVARIABLE_H
#define GLOBALVARIABLE_H

    #include <vector>
    ////////////////////////////////////////
    extern long lFA_MTPulse;
    extern long lNoOfMTPulses;
    extern long ltDK_MTPulse_Duration_us;
    //extern long ltDK_MTPulse_Delay_us;
    extern long ltDK_Wait_After_MT_us;
    extern long ltDK_Wait_After_MTSpoil_us;
    extern long lNoOfMTPulses_PerRTEB;
    extern long ltDK_PreAcqCESTPulseTime_ms;
    extern long ltDK_PreAcqCESTPulseTime_us;
    extern long lTest_XgradStrength;
    //double TR_MTPulse_Remain = 0.0;                                                                   // CEST This will be calculated later 
    long ltDK_TR_MTPulse_us;
    long ltDK_TimeNeeded_for_sMTCSpoilerOnly;
    long ltDK_MTBlockTime_DK;

    ////////////////////////////////////////
    extern double dBWTimeProd;
    extern double dSpoilerCTRL;
    extern double dOffResonance_Rel;
    ////////////////////////////////////////
    long No_of_Samples = (long)512;                                                                     // CEST
    long lNo_of_MTPulses_PreAcq;
    //static sRF_PULSE  sRfMSat1("sRfMSat");                                                        // CEST("sRfMSat")

    extern long lNoOfKSpaceAcq_PerCEST_ArrayValues[];


#endif

In GlobalVariable.cpp

// NOTE: usually name of any parameters is prefixed by type e.g. 
// I am introducing another parameter with prefix "ltDK_" for "long-time" parameter 
//
long lFA_MTPulse = 100;
long lNoOfMTPulses = 1;
long ltDK_MTPulse_Duration_us = 10000;
//long ltDK_MTPulse_Delay_us = 10000;
long ltDK_Wait_After_MT_us = 0;
long ltDK_Wait_After_MTSpoil_us = 0;
long ltDK_PreAcqCESTPulseTime_ms = 3500;                                                // in micro sec 
long ltDK_PreAcqCESTPulseTime_us = (long)((double)ltDK_PreAcqCESTPulseTime_ms*1000);    // in milli sec
long lTest_XgradStrength = 0;

long lNoOfMTPulses_PerRTEB = 30;
double dBWTimeProd = 1.79;
double dSpoilerCTRL = 1.0;
double dOffResonance_Rel = 0.0;
long lNoOfKSpaceAcq_PerCEST_ArrayValues[5] = {1, 3, 5, 7, 9};
2

There are 2 answers

0
Benoit Blanchon On BEST ANSWER

You must declare every variable as extern in the .h file, otherwise it will exist in each .c file that include the .h.

extern means that the linker find the variables in another file, in you case it'll find the variables in GlobalVariables.o

Also, you need to understand that #include insert the text of the .h in your .c, so each statement in the .h is repeated in each .c. This is what happens to ltDK_TR_MTPulse_us for instance: it is declared in both CEST.cpp and CEST_UI.cpp, so the linker sees two variables of the same name, which is forbidden.

1
Jesse Good On

Include guards prevent one source file from including the same header more than once. They do not prevent multiple definition errors. Move all your definitions in the header to a source file and declare them as extern in the header. Separate sources files will include that header and you will get multiple definition errors.