C++ 链接错误与 Linux 上的多个定义

Posted

技术标签:

【中文标题】C++ 链接错误与 Linux 上的多个定义【英文标题】:C++ linking error with multiple definition on linux 【发布时间】:2013-09-12 11:40:31 【问题描述】:

我正在尝试编译一个代码,但它遇到了包含多个定义的链接错误。不幸的是,我无法修复它,我们将不胜感激。

我有以下文件: 头文件:CEST.h; CEST_UI.h;全局变量.h; 源文件:CEST.cpp; CEST_UI.cpp;全局变量.cpp

所有声称有多重定义的参数,在“GlobalVariable.h”中定义,在“GlobalVariable.cpp”中初始化。

我包含“GlobalVariable.h”两次:一次在 CEST.cpp 中,第二次在 CEST_UI.cpp 中。

我在想“GlobalVariable.h”中的以下守卫会保护我免受多定义链接错误的影响:

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

我还附上“GlobalVariable.h”和“GlobalVariable.cpp”,方便大家看看。

在“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

在 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;

【问题讨论】:

标题中缺少一些externs。 【参考方案1】:

您必须在.h 文件中将每个变量声明为extern,否则它将存在于每个包含.h.c 文件中。

extern 表示链接器在另一个文件中查找变量,在您的情况下它会在GlobalVariables.o 中查找变量

另外,您需要了解#include.c 中插入.h文本,因此.h 中的每个语句在每个.c 中重复。 这就是 ltDK_TR_MTPulse_us 发生的情况,例如:它在 CEST.cppCEST_UI.cpp 中都声明了,因此链接器会看到两个同名的变量,这是被禁止的。

【讨论】:

【参考方案2】:

包含保护可防止一个源文件多次包含同一个标头。它们防止出现多个定义错误。将标头中的所有定义移动到源文件中,并在标头中将它们声明为extern。单独的源文件将包含该标头,您将收到多个定义错误。

【讨论】:

这是我所缺少的关键!我使用“config.h”文件作为全局配置。当我开始将功能拆分为不同的文件并尝试#include config.h(即使使用extern)时,它给出了链接器错误。将声明 (extern int x;) 放入 .h 文件并将定义 (int x=1;) 放入 .cpp 后,一切正常。谢谢!

以上是关于C++ 链接错误与 Linux 上的多个定义的主要内容,如果未能解决你的问题,请参考以下文章

如何正确链接 Linux 上的 lua 库?

在 linux 中编译/链接多个 c++ 库

Borland C++ Builder 6 上的奇怪链接器错误

为啥我应该没有错时却出现链接错误

如何将 libcurl 与 dev c++ 静态链接?

GCC中的弱符号与强符号