【问题标题】:Multiple definition of a global variable [duplicate]全局变量的多重定义[重复]
【发布时间】:2013-01-09 16:09:48
【问题描述】:

可能重复:
constant variables not working in header

在我用来创建共享对象的头文件中,我有以下内容:

#ifndef LIB_HECA_DEF_H_
#define LIB_HECA_DEF_H_

struct dsm_config {
    int auto_unmap;
    int enable_copy_on_access;
};

enum { NO_AUTO_UNMAP, AUTO_UNMAP } unmap_flag;
enum { NO_ENABLE_COA, ENABLE_COA } coa_flag;

const struct dsm_config DEFAULT_DSM_CONFIG = { AUTO_UNMAP, NO_ENABLE_COA };

<more code ...>

#endif

编译时出现以下错误:

cc -g -Wall -pthread libheca.c dsm_init.c -DDEBUG    master.c   -o master
/tmp/cciBnGer.o:(.rodata+0x0): multiple definition of `DEFAULT_DSM_CONFIG'
/tmp/cckveWVO.o:(.rodata+0x0): first defined here
collect2: ld returned 1 exit status
make: *** [master] Error 1

有什么想法吗?

【问题讨论】:

  • 使用不同的命名空间

标签: c makefile shared-libraries


【解决方案1】:

因为每次包含在实现文件文件中,都会创建一个新的结构实例(并存储在目标文件中)。

为避免这种情况,只需在头文件中将结构声明为“extern”并在实现文件中对其进行初始化:

// In your header file: 
extern const struct dsm_config DEFAULT_DSM_CONFIG;

// In your *.c file:
const struct dsm_config DEFAULT_DSM_CONFIG = { AUTO_UNMAP, NO_ENABLE_COA };

这将解决您的问题。

【讨论】:

    【解决方案2】:

    在 C 语言中,const 对象默认具有外部链接(与 C++ 中它们默认具有内部链接相反)。因此,在您的代码中,您使用外部链接创建了对象 DEFAULT_DSM_CONFIG 的多个定义 - 这明显违反了 C 语言的定义规则。

    要么将你的对象声明为static const(如果你不介意有多个具有内部链接的对象)或从头文件中删除定义(只留下一个非定义的extern const 声明那里)。

    不管怎样,这个问题已经被问过很多次了。请参阅constant variables not working in header 或进行搜索。

    【讨论】:

      【解决方案3】:

      每个包含头文件的 c 文件都有一行

      const struct dsm_config DEFAULT_DSM_CONFIG = { AUTO_UNMAP, NO_ENABLE_COA };

      所以这些 c 文件中的每一个都定义了一个变量 dsm_config。如果只需要一个变量 dsm_config 则需要将头文件中的声明更改为

      extern const struct dsm_config DEFAULT_DSM_CONFIG;

      并添加定义

      const struct dsm_config DEFAULT_DSM_CONFIG = { AUTO_UNMAP, NO_ENABLE_COA };

      仅在一个 c 文件中。

      另一个不太好的解决方案是将头文件更改为

      static const struct dsm_config DEFAULT_DSM_CONFIG = { AUTO_UNMAP, NO_ENABLE_COA };

      然后每个 c 文件定义它自己的 dsm_config,在链接期间其他翻译单元不可见。

      【讨论】:

        【解决方案4】:

        每个源文件(.c,而不是 .h)都是单独编译的。在这些编译中,dsm_config 的声明带有一个初始化器(= { values… } 部分)创建了一个dsm_config 的定义。因此,整个程序有多个定义。

        一般来说,头文件应该只声明对象而不是定义它们。为此,请删除头文件中的初始化程序,只留下没有初始化程序的声明。在一个源文件中,通过使用初始化程序重复声明来定义dsm_config

        【讨论】:

          猜你喜欢
          • 2021-03-11
          • 2020-04-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-11-15
          • 1970-01-01
          • 2022-01-28
          相关资源
          最近更新 更多