C++ 带有C头的重复符号问题

C++ 带有C头的重复符号问题,c++,c,cuda,header-files,duplicate-symbol,C++,C,Cuda,Header Files,Duplicate Symbol,这是我第一次处理CUDA项目,它比简单的编写单个源文件和编译例程稍微复杂一些。正如所料,我在使用C头时遇到了一些问题,即重复符号 根据链接器,在多个.cu文件中包含以下头文件会产生冲突: env_vars.h #ifndef ENV_VARS_H_ #define ENV_VARS_H_ /*** GLOBAL VARIABLES ***/ unsigned int h_n_osc; __device__ unsigned int d_n_osc; /*** CONSTANTS ***/ c

这是我第一次处理CUDA项目,它比简单的编写单个源文件和编译例程稍微复杂一些。正如所料,我在使用C头时遇到了一些问题,即重复符号

根据链接器,在多个
.cu
文件中包含以下头文件会产生冲突:

env_vars.h

#ifndef ENV_VARS_H_
#define ENV_VARS_H_

/*** GLOBAL VARIABLES ***/
unsigned int h_n_osc;
__device__ unsigned int d_n_osc;

/*** CONSTANTS ***/
const double OMEGA_0 = 6.447421494058077e+09;

/* other constants defined in the middle */

#endif
multigpu.cu

#include "env_vars.h"
/* assigns h_n_osc */
#include "env_vars.h"
/* uses h_n_osc */
#include "env_vars.h"
unsigned int h_n_osc;
adm_matrix.cu

#include "env_vars.h"
/* assigns h_n_osc */
#include "env_vars.h"
/* uses h_n_osc */
#include "env_vars.h"
unsigned int h_n_osc;
在Nsight Eclipse版本中构建项目会导致链接器抱怨
h\u n\u osc
变量被定义了两次:

duplicate symbol _h_n_osc in:
    ./adm_matrix.o
    ./multigpu.o
ld: 1 duplicate symbol for architecture x86_64
通过互联网搜索,我意识到将
h\u n\u osc
变量的声明移动到
multigpu.cu
,并在
adm\u matrix.cu
中重新声明为
extern
变量(以及以后可能需要它的任何地方)可以解决问题,事实上它确实解决了这个问题

问题已解决,但我想对此进行更深入的研究:

  • 为什么链接器也不抱怨
    d\n\u osc
    变量?为什么常数(比如ω0)同样不是问题
  • 这是否意味着无法在头文件中放置全局变量
  • 最让我困惑的是,互联网上的许多来源都声明,重复的符号错误只有在头文件包含变量定义时才会发生,而它的简单声明不应该构成问题。我很难相信这一点的原因是,即使我的标题只包含一个声明,我也面临着这个问题!我错过什么了吗

  • 各位,提前感谢你们的耐心等待

    头文件通常只应包含声明性代码
    h_n_osc
    应在此处声明,而不是定义

    在至少一个模块中,或者在一个新模块中,您需要一个定义;例如:

    环境变量cu

    #include "env_vars.h"
    /* assigns h_n_osc */
    
    #include "env_vars.h"
    /* uses h_n_osc */
    
    #include "env_vars.h"
    unsigned int h_n_osc;
    
    然后把它链接起来。当然,您也可以将定义放在现有模块multigpu.cu或adm_matrix.cu中


    我不确定扩展的语义,虽然它可能链接,但不一定正确;最终,每个模块可能引用设备变量的单独副本;可能还需要使用
    extern
    对其进行限定。似乎解决了这个问题。

    信不信由你,
    未签名的int h_n_osc
    是一个定义。请在单个.c文件中定义变量,然后头文件需要对这些变量使用“extern”语句冲击揭露,@aschepler!事实证明,我一直误解了变量的声明和定义之间的区别。非常感谢。正确,
    \uuuuuuu设备\uuuuuu
    (和
    \uuuuu常量\uuuuuuuuu
    )变量。@RobertCrovella:谢谢;因此,它们的语义与
    静态
    常量
    相似,这似乎是一个问题。但我会说是的,类似的。在没有其他细节的情况下,CUDA应该与C++编译器的行为类似。代码> >“Deice”/“代码>和<代码>·y-康斯坦特变量在普通的主机C++代码中是不可引用的,但这是一个单独的主题。谢谢你们,伙计们!正如我在上面所评论的,我的大多数怀疑显然源于我对声明和变量定义的概念的误解。为了完整性,这里的栈溢出也回答了我原来的帖子中的问题2:<代码> const <代码>蚂蚁在C++中有默认的内部链接(而它们默认为C中的外部链接),所以我的解决方案(即在头中定义它们)很好,因为CUDA C实际上是CUDA C/C++;纯C编译器也会拒绝这些常数。@ TeQueCurrad:如果你声明const的代码>静态const < /> >,那么C和C++中的语义是相同的。但是,如果代码占用了const的地址,那么它们在每个模块中都是不同的,但是在C++中,至少如果不使用const的地址,所有引用都会被文字替换。