与const char *[]声明相关联的重复符号错误

时间:2021-12-31 04:51:39

I'd love help diagnosing the source of a duplicate symbol error that I'm receiving when I try to compile with g++ 4.2.1.

我很想帮助您诊断当我尝试使用g++ 4.2.1编译时所收到的重复符号错误的来源。

The specific error is

具体的错误是

ld: duplicate symbol _SOCIODEM_FILENAMES in /var/folders/c+/c+eq1Qz1Feye7vxs5mQOUE+++TI/-Tmp-//ccP3yVgF.o and /var/folders/c+/c+eq1Qz1Feye7vxs5mQOUE+++TI/-Tmp-//cc1NqtRL.o 
collect2: ld returned 1 exit status

The error occurs only when I include this declaration in a file called Parameters.h:

只有当我将这个声明包含在一个名为Parameters.h的文件中时,才会出现错误。

// Parameters.h

#ifndef PARAMETERS_H
#define PARAMETERS_H

// ...[code snipped]...
const int NUM_SOCIODEM_FILES = 5;
const char * SOCIODEM_FILENAMES[ NUM_SOCIODEM_FILES ] = { "LSPAN_PDF.txt", 
     "FLEDGE_PDF.txt", 
     "PAIR_PDF.txt", 
     "BIRTH_AGE_PDF.txt",  
     "SPLIT_PDF.txt"  };
// ...[code snipped]...
#endif

I've searched all my files, and this is the only place where SOCIODEM_FILENAMES is declared. When I comment out the declaration, the 'duplicate symbol' error goes away.

我搜索了所有的文件,这是唯一一个声明社会名的地方。当我注释掉声明时,“重复符号”错误就消失了。

I'm unfamiliar with linker errors (if that's what this is) and would appreciate help troubleshooting the problem. All my header files have #ifndef...#define...#endif wrappers. My compile command is

我不熟悉链接器错误(如果是这样的话),希望能帮助解决问题。我所有的头文件都有#ifndef…#define…# endif包装器。我的编译命令

g++ -o a.out -I /Applications/boost_1_42_0/ Host.cpp Simulation.cpp main.cpp Rdraws.cpp

Thanks in advance.

提前谢谢。


Solution summary

解决方案概述

I now have in Parameters.h:

我现在有了护理人员。

const char * const SOCIODEM_FILENAMES[ NUM_SOCIODEM_FILES ] = { "LSPAN_PDF.txt", 
                 "FLEDGE_PDF.txt", 
                 "PAIR_PDF.txt", 
                 "BIRTH_AGE_PDF.txt",  
                 "SPLIT_PDF.txt"  };

All other definitions and declarations in Parameters.h are unchanged. Andrey and other commenters summarize an alternative approach using extern, which is overkill for my purposes.

所有其他定义和参数声明。h是不变。Andrey和其他评论者总结了一种使用外部的替代方法,这是为了我的目的而过度使用的。

5 个解决方案

#1


14  

For some reason none of the answers so far cared to explain the difference between your integer NUM_SOCIODEM_FILES object and array SOCIODEM_FILENAMES object. The latter triggers the linker error for the reasons already explained: because you include you header file into multiple implementation files. Yet, the former would link without any problems (because there are indeed no problems with NUM_SOCIODEM_FILES declaration). Why?

由于某种原因,到目前为止,没有一个答案愿意解释整数num_社会dem_files对象和数组社会dem_filenames对象之间的区别。后者触发链接器错误的原因已经说明:因为您将头文件包含到多个实现文件中。但是,前者链接时没有任何问题(因为num_社会dem_files声明确实没有问题)。为什么?

The reason for this is that your NUM_SOCIODEM_FILES object is declared const. In C++ const objects have internal linkage by default, meaning that they do not cause linking problems even if they are defined in multiple implementation files. In other words, in C++ your NUM_SOCIODEM_FILES is equivalent to

这样做的原因是,您的num_social dem_files对象被声明为const。在c++ const对象中,默认情况下具有内部链接,这意味着即使在多个实现文件中定义了链接,它们也不会导致链接问题。换句话说,在c++中,您的num_社会dem_files等于

static const int NUM_SOCIODEM_FILES = 5; /* internal linkage */

which is why it does not lead to any linking problems.

这就是为什么它不会导致任何链接问题。

At the same time your SOCIODEM_FILENAMES is not declared constant, which is why it gets external linkage by default and eventually leads to linker errors. But if you declare your SOCIODEM_FILENAMES as const as well, the problem will go away

同时,您的社会性dem_filenames没有被声明为常量,这就是为什么它默认地获得外部链接,并最终导致链接器错误。但是,如果您也将您的社会性dem_filename声明为const,那么问题就会消失

const char * const SOCIODEM_FILENAMES[ NUM_SOCIODEM_FILES ] = {
  ...

Note where the extra const is placed in the declaration. If you just add that extra const and leave everything else as is (i.e. keep the definition if SOCIODEM_FILENAMES in the header file), the linker will not report the error even if you include your header file into multiple translation units.

注意在声明中放置额外的常量的位置。如果您只是添加额外的const并保留其他所有内容(例如,如果在头文件中保留社会dem_filenames的定义),即使您将头文件包含到多个转换单元中,链接器也不会报告错误。

This is not a recommended approach though, since that way you will give your SOCIODEM_FILENAMES internal linkage and end up with a standalone copy of SOCIODEM_FILENAMES array in each translation unit - something that might work fine but still makes very little sense. So, for your array, it is normally better to use the extern approach recommended in other answers.

但这并不是推荐的方法,因为这样你就可以在每个翻译单元中给你的社会角色文件名内部链接,并得到一个独立的社会dem_filenames数组的副本——这可能会很好,但仍然没有什么意义。因此,对于数组,通常最好使用其他答案中推荐的extern方法。

However, note that you shouldn't normally do it for NUM_SOCIODEM_FILES declaration!!! It is fine as it is, defined in the header file. Unless you are trying to do something unusual, scalar constants should normally be defined with initializer in the header files - that way they can be seen as compile-time constants in all translation units, which is a rather valuable thing to have. So, beware of the strange advice present in some other answers to move the definition of NUM_SOCIODEM_FILES into .cpp file as well - this actually makes no sense and is a totally wrong thing to do.

但是,请注意,您通常不应该对num_社会dem_files声明这样做!!它可以在头文件中定义。除非您正在尝试做一些不寻常的事情,否则标头文件中的初始化器通常应该定义标量常量——这样它们就可以被视为所有转换单元中的编译时常量,这是非常有价值的。因此,请注意在其他一些答案中出现的奇怪建议,将num_社会dem_files的定义移到.cpp文件中——这实际上毫无意义,而且是完全错误的做法。

#2


7  

Most likely, you are #includeing this file in multiple source files. The problem is that each inclusion results in a separate definition for a variable named SOCIODEM_FILENAMES. Include guards do not help with this. Include guards prevent multiple declarations within a single compilation unit; they do not prevent multiple definitions across several compilation units.

很有可能,您在多个源文件中包含这个文件。问题是,每个包含都会产生一个单独的定义,用于命名为社会性dem_filenames的变量。包括守卫不帮忙。在一个编译单元中包含防止多个声明的保护;它们不阻止多个编译单元之间的多个定义。

What you need to do is declare these variables as extern in the header, and then define them in exactly one source file. e.g.

您需要做的是将这些变量声明为header中的extern,然后在一个源文件中定义它们。如。

// Parameters.h

#ifndef PARAMETERS_H
#define PARAMETERS_H

// ...[code snipped]...
extern const int NUM_SOCIODEM_FILES;
extern const char * SOCIODEM_FILENAMES[];
// ...[code snipped]...
#endif

and then:

然后:

// Parameters.cpp (or some other source file)

const int NUM_SOCIODEM_FILES = 5;    
const char * SOCIODEM_FILENAMES[ NUM_SOCIODEM_FILES ] = { "LSPAN_PDF.txt", 
                 "FLEDGE_PDF.txt", 
                 "PAIR_PDF.txt", 
                 "BIRTH_AGE_PDF.txt",  
                 "SPLIT_PDF.txt"  };

You can get away with not doing this for the int because it is a constant integer, and so the compiler can just treat it as a compile-time constant, and it will never even show up in the compiled code. However, the char* cannot be treated this way, and so must have exactly one definition (known as the "one definition rule" in C++).

你可以不这样做,因为它是一个常量整数,所以编译器可以把它当作编译时常量,它甚至不会出现在编译后的代码中。但是,char*不能这样处理,因此必须有一个定义(在c++中称为“一个定义规则”)。

#3


2  

The header guard (#ifndef..#endif wrapper) just prevents you from including the same header multiple times in a single source file. You can still have multiple source files that include that header, and each one will declare that symbol separately. Since they all have the same name, linking those sources together will cause a symbol name collision. You probably want to declare the symbol in a source file instead of a header file

头卫队(ifndef . .#endif包装)只是阻止您在一个源文件中多次包含相同的头。您仍然可以拥有包含该头的多个源文件,每个文件将分别声明该符号。由于它们都有相同的名称,将这些源链接在一起将导致符号名称冲突。您可能希望在源文件而不是头文件中声明符号

#4


2  

The problem is you are putting a definition in a header file. If you include that file in more than one compilation unit (.cpp file) you will be in effect creating multiple definitions and at link time you will get that error.

问题是,您正在将一个定义放入头文件中。如果您将该文件包含在多个编译单元(。您将实际创建多个定义,在链接时您将得到该错误。

You need to put both those definitions in a .cpp file and put only a declaration in the header file:

您需要将这两个定义都放在.cpp文件中,并且只在头文件中放入一个声明:

extern const int NUM_SOCIODEM_FILES;
extern const char * SOCIODEM_FILENAMES[];

#5


2  

As others have suggested, one way of doing this is to declare NUM_SOCIODEM_FILES and SOCIODEM_FILENAMES as extern and define them once in an external file. The other way is to declare them as static--this causes them to be duplicated in every object file that includes the header, but will not create an error since the definition is private to that object file. Which option you choose is entirely up to your own preferences.

正如其他人所建议的那样,这样做的一种方法是将num_social dem_files和social dem_filenames声明为外部文件,并在外部文件中定义它们。另一种方法是将它们声明为静态——这将导致它们在包含头的每个对象文件中被复制,但是不会创建错误,因为定义是该对象文件的私有属性。你选择的选项完全取决于你自己的喜好。

#1


14  

For some reason none of the answers so far cared to explain the difference between your integer NUM_SOCIODEM_FILES object and array SOCIODEM_FILENAMES object. The latter triggers the linker error for the reasons already explained: because you include you header file into multiple implementation files. Yet, the former would link without any problems (because there are indeed no problems with NUM_SOCIODEM_FILES declaration). Why?

由于某种原因,到目前为止,没有一个答案愿意解释整数num_社会dem_files对象和数组社会dem_filenames对象之间的区别。后者触发链接器错误的原因已经说明:因为您将头文件包含到多个实现文件中。但是,前者链接时没有任何问题(因为num_社会dem_files声明确实没有问题)。为什么?

The reason for this is that your NUM_SOCIODEM_FILES object is declared const. In C++ const objects have internal linkage by default, meaning that they do not cause linking problems even if they are defined in multiple implementation files. In other words, in C++ your NUM_SOCIODEM_FILES is equivalent to

这样做的原因是,您的num_social dem_files对象被声明为const。在c++ const对象中,默认情况下具有内部链接,这意味着即使在多个实现文件中定义了链接,它们也不会导致链接问题。换句话说,在c++中,您的num_社会dem_files等于

static const int NUM_SOCIODEM_FILES = 5; /* internal linkage */

which is why it does not lead to any linking problems.

这就是为什么它不会导致任何链接问题。

At the same time your SOCIODEM_FILENAMES is not declared constant, which is why it gets external linkage by default and eventually leads to linker errors. But if you declare your SOCIODEM_FILENAMES as const as well, the problem will go away

同时,您的社会性dem_filenames没有被声明为常量,这就是为什么它默认地获得外部链接,并最终导致链接器错误。但是,如果您也将您的社会性dem_filename声明为const,那么问题就会消失

const char * const SOCIODEM_FILENAMES[ NUM_SOCIODEM_FILES ] = {
  ...

Note where the extra const is placed in the declaration. If you just add that extra const and leave everything else as is (i.e. keep the definition if SOCIODEM_FILENAMES in the header file), the linker will not report the error even if you include your header file into multiple translation units.

注意在声明中放置额外的常量的位置。如果您只是添加额外的const并保留其他所有内容(例如,如果在头文件中保留社会dem_filenames的定义),即使您将头文件包含到多个转换单元中,链接器也不会报告错误。

This is not a recommended approach though, since that way you will give your SOCIODEM_FILENAMES internal linkage and end up with a standalone copy of SOCIODEM_FILENAMES array in each translation unit - something that might work fine but still makes very little sense. So, for your array, it is normally better to use the extern approach recommended in other answers.

但这并不是推荐的方法,因为这样你就可以在每个翻译单元中给你的社会角色文件名内部链接,并得到一个独立的社会dem_filenames数组的副本——这可能会很好,但仍然没有什么意义。因此,对于数组,通常最好使用其他答案中推荐的extern方法。

However, note that you shouldn't normally do it for NUM_SOCIODEM_FILES declaration!!! It is fine as it is, defined in the header file. Unless you are trying to do something unusual, scalar constants should normally be defined with initializer in the header files - that way they can be seen as compile-time constants in all translation units, which is a rather valuable thing to have. So, beware of the strange advice present in some other answers to move the definition of NUM_SOCIODEM_FILES into .cpp file as well - this actually makes no sense and is a totally wrong thing to do.

但是,请注意,您通常不应该对num_社会dem_files声明这样做!!它可以在头文件中定义。除非您正在尝试做一些不寻常的事情,否则标头文件中的初始化器通常应该定义标量常量——这样它们就可以被视为所有转换单元中的编译时常量,这是非常有价值的。因此,请注意在其他一些答案中出现的奇怪建议,将num_社会dem_files的定义移到.cpp文件中——这实际上毫无意义,而且是完全错误的做法。

#2


7  

Most likely, you are #includeing this file in multiple source files. The problem is that each inclusion results in a separate definition for a variable named SOCIODEM_FILENAMES. Include guards do not help with this. Include guards prevent multiple declarations within a single compilation unit; they do not prevent multiple definitions across several compilation units.

很有可能,您在多个源文件中包含这个文件。问题是,每个包含都会产生一个单独的定义,用于命名为社会性dem_filenames的变量。包括守卫不帮忙。在一个编译单元中包含防止多个声明的保护;它们不阻止多个编译单元之间的多个定义。

What you need to do is declare these variables as extern in the header, and then define them in exactly one source file. e.g.

您需要做的是将这些变量声明为header中的extern,然后在一个源文件中定义它们。如。

// Parameters.h

#ifndef PARAMETERS_H
#define PARAMETERS_H

// ...[code snipped]...
extern const int NUM_SOCIODEM_FILES;
extern const char * SOCIODEM_FILENAMES[];
// ...[code snipped]...
#endif

and then:

然后:

// Parameters.cpp (or some other source file)

const int NUM_SOCIODEM_FILES = 5;    
const char * SOCIODEM_FILENAMES[ NUM_SOCIODEM_FILES ] = { "LSPAN_PDF.txt", 
                 "FLEDGE_PDF.txt", 
                 "PAIR_PDF.txt", 
                 "BIRTH_AGE_PDF.txt",  
                 "SPLIT_PDF.txt"  };

You can get away with not doing this for the int because it is a constant integer, and so the compiler can just treat it as a compile-time constant, and it will never even show up in the compiled code. However, the char* cannot be treated this way, and so must have exactly one definition (known as the "one definition rule" in C++).

你可以不这样做,因为它是一个常量整数,所以编译器可以把它当作编译时常量,它甚至不会出现在编译后的代码中。但是,char*不能这样处理,因此必须有一个定义(在c++中称为“一个定义规则”)。

#3


2  

The header guard (#ifndef..#endif wrapper) just prevents you from including the same header multiple times in a single source file. You can still have multiple source files that include that header, and each one will declare that symbol separately. Since they all have the same name, linking those sources together will cause a symbol name collision. You probably want to declare the symbol in a source file instead of a header file

头卫队(ifndef . .#endif包装)只是阻止您在一个源文件中多次包含相同的头。您仍然可以拥有包含该头的多个源文件,每个文件将分别声明该符号。由于它们都有相同的名称,将这些源链接在一起将导致符号名称冲突。您可能希望在源文件而不是头文件中声明符号

#4


2  

The problem is you are putting a definition in a header file. If you include that file in more than one compilation unit (.cpp file) you will be in effect creating multiple definitions and at link time you will get that error.

问题是,您正在将一个定义放入头文件中。如果您将该文件包含在多个编译单元(。您将实际创建多个定义,在链接时您将得到该错误。

You need to put both those definitions in a .cpp file and put only a declaration in the header file:

您需要将这两个定义都放在.cpp文件中,并且只在头文件中放入一个声明:

extern const int NUM_SOCIODEM_FILES;
extern const char * SOCIODEM_FILENAMES[];

#5


2  

As others have suggested, one way of doing this is to declare NUM_SOCIODEM_FILES and SOCIODEM_FILENAMES as extern and define them once in an external file. The other way is to declare them as static--this causes them to be duplicated in every object file that includes the header, but will not create an error since the definition is private to that object file. Which option you choose is entirely up to your own preferences.

正如其他人所建议的那样,这样做的一种方法是将num_social dem_files和social dem_filenames声明为外部文件,并在外部文件中定义它们。另一种方法是将它们声明为静态——这将导致它们在包含头的每个对象文件中被复制,但是不会创建错误,因为定义是该对象文件的私有属性。你选择的选项完全取决于你自己的喜好。