gcc/g++和全局变量的多重定义
gcc/g++ and multiple definitions of global variables
我有几个 .h/.cpp 文件,每个文件都应该有名为 "common.h / common.cpp" 的文件,因为我在我的其余文件中重复使用它的定义。 common.h 文件定义了一些有意的全局变量。
我在 Linux 和 gcc 4.4.7 下工作。
Compuler 工作正常,但 g++ 链接器在很多情况下都会抱怨:
build/Debug/GNU-Linux-x86/StoreData2/spacewx.o:(.data+0x200): multiple definition of `nmdata::names`
build/Debug/GNU-Linux-x86/StoreData2/StoreData2.o:(.data+0x200): first defined here
因此我没有获得成功的构建。请建议如何摆脱这个错误,并保留这些全局变量。到目前为止,我只使用函数式编程(使用 C++ 库,例如 boost)并且没有自己的 namespaces/objects。
假设您的全局 header 是 (global.h
):
#ifndef _GLOBAL_H
#define _GLOBAL_H
int g_a;
#endif
如果您有两个源文件,包括 global.h
:a.cpp
和 b.cpp
,如下所示:
a.cpp
#include "global.h"
/* some source */
b.cpp
#include "global.h"
/* some source */
预处理后它们将如下所示(包含的文件已展开):
a.cpp
int g_a;
/* some source */
b.cpp
int g_a;
/* some source */
因此,如果您编译这些源文件,全局变量int g_a
将被定义在两个object 文件中。所以链接器会抱怨多个定义。
要克服这个问题,您需要 header 中的 extern
关键字。 extern
关键字告诉编译器该变量在别处定义。因此,不会将新的全局 object 条目写入 object 文件。
更改 global.h
如下:
#ifndef _GLOBAL_H
#define _GLOBAL_H
extern int g_a;
#endif
因此,不会有 int g_a
条目写入 object 文件。但这会导致链接中出现未定义的符号错误。要克服这个问题,请在 a.cpp
或 b.cpp
中定义 int g_a
,但不要同时在两者中定义。
b.cpp
#include "global.h"
int g_a;
/* some source */
程序中的每个变量或函数在一个编译单元中只能定义一次。如果你在多个编译单元中 define 任何东西,你通常会得到一个 link 错误,就像你看到的那样,虽然正式地,它是未定义的行为,所以编译器可能不会进行诊断,您的程序就会出现异常。
你的程序中可以有多个声明,所以通常你设置的东西让你的头文件有ONLY声明, 包含 .cpp 文件中的所有定义。
我有几个 .h/.cpp 文件,每个文件都应该有名为 "common.h / common.cpp" 的文件,因为我在我的其余文件中重复使用它的定义。 common.h 文件定义了一些有意的全局变量。
我在 Linux 和 gcc 4.4.7 下工作。
Compuler 工作正常,但 g++ 链接器在很多情况下都会抱怨:
build/Debug/GNU-Linux-x86/StoreData2/spacewx.o:(.data+0x200): multiple definition of `nmdata::names`
build/Debug/GNU-Linux-x86/StoreData2/StoreData2.o:(.data+0x200): first defined here
因此我没有获得成功的构建。请建议如何摆脱这个错误,并保留这些全局变量。到目前为止,我只使用函数式编程(使用 C++ 库,例如 boost)并且没有自己的 namespaces/objects。
假设您的全局 header 是 (global.h
):
#ifndef _GLOBAL_H
#define _GLOBAL_H
int g_a;
#endif
如果您有两个源文件,包括 global.h
:a.cpp
和 b.cpp
,如下所示:
a.cpp
#include "global.h"
/* some source */
b.cpp
#include "global.h"
/* some source */
预处理后它们将如下所示(包含的文件已展开):
a.cpp
int g_a;
/* some source */
b.cpp
int g_a;
/* some source */
因此,如果您编译这些源文件,全局变量int g_a
将被定义在两个object 文件中。所以链接器会抱怨多个定义。
要克服这个问题,您需要 header 中的 extern
关键字。 extern
关键字告诉编译器该变量在别处定义。因此,不会将新的全局 object 条目写入 object 文件。
更改 global.h
如下:
#ifndef _GLOBAL_H
#define _GLOBAL_H
extern int g_a;
#endif
因此,不会有 int g_a
条目写入 object 文件。但这会导致链接中出现未定义的符号错误。要克服这个问题,请在 a.cpp
或 b.cpp
中定义 int g_a
,但不要同时在两者中定义。
b.cpp
#include "global.h"
int g_a;
/* some source */
程序中的每个变量或函数在一个编译单元中只能定义一次。如果你在多个编译单元中 define 任何东西,你通常会得到一个 link 错误,就像你看到的那样,虽然正式地,它是未定义的行为,所以编译器可能不会进行诊断,您的程序就会出现异常。
你的程序中可以有多个声明,所以通常你设置的东西让你的头文件有ONLY声明, 包含 .cpp 文件中的所有定义。