C 标头存在重复符号问题

Duplicate symbol issue with C headers

本文关键字:符号 问题 存在      更新时间:2023-10-16

这是我第一次处理比简单的写入单源文件和编译例程稍微复杂的 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 */

adm_matrix.cu

#include "env_vars.h"
/* uses h_n_osc */

在 Nsight Eclipse Edition 中构建项目会导致链接器抱怨h_n_osc变量被定义两次:

duplicate symbol _h_n_osc in:
    ./adm_matrix.o
    ./multigpu.o
ld: 1 duplicate symbol for architecture x86_64

在互联网上搜索,我意识到将h_n_osc变量的声明移动到multigpu.cu并将其重新声明为adm_matrix.cu中的extern变量(以及我以后可能需要它的地方(可以解决问题,事实上它确实如此

问题解决了,但我想更深入地研究一下:

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

提前感谢您的耐心等待,伙计们!

头文件通常应包含声明性代码。 h_n_osc应该在这里声明,而不是定义

extern unsigned int h_n_osc;

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

env_vars.铜

#include "env_vars.h"
unsigned int h_n_osc;

然后链接它。 或者,您当然可以将定义放在现有模块之一中 multigpu.cu 或 adm_matrix.cu。

我不确定 CUDA __device__ 扩展的语义,虽然它可能链接,但它不一定正确;你最终可能会得到每个模块引用设备变量的单独副本;可能也有必要用extern来限定它。 这个问题似乎涉及这个问题。