多重定义...链接器错误

Multiple definition of ... linker error

提问人:mazix 提问时间:7/21/2013 最后编辑:mazix 更新时间:2/7/2022 访问量:184300

问:

我定义了一个特殊的文件:config.h

我的项目也有文件:

t.c, t.h
pp.c, pp.h
b.c b.h
l.cpp

以及 #includes:

在T.C.中:

    #include "t.h"
    #include "b.h"
    #include "pp.h"
    #include "config.h"

在不列颠哥伦比亚省:

    #include "b.h"
    #include "pp.h"

在pp.c中:

    #include "pp.h"
    #include "config.h"

在 l.cpp 中:

    #include "pp.h"
    #include "t.h"
    #include "config.h"

“我的文件”中没有 include 指令,只有“文件”中的包含指令。我在config.h中定义了这一点:*.h*.c

const char *names[i] =
        {
            "brian", "stefan", "steve"
        };

并且需要 l.cpp、t.c、pp.c 中的数组,但我收到此错误:

pp.o:(.data+0x0): multiple definition of `names'
l.o:(.data+0x0): first defined here
t.o:(.data+0x0): multiple definition of `names'
l.o:(.data+0x0): first defined here
collect2: ld returned 1 exit status
make: *** [link] Error 1

我在项目中使用的每个文件中都包含防护装置。有什么帮助解决这个问题吗?*.h

c 链接 链接器错误

评论

0赞 7/21/2013
将函数添加到以前的链接文件后,可能重复多个定义链接器错误
1赞 eftshift0 8/15/2020
debian 最近有什么变化吗?直到几天,我的项目编译得很好......在最近的更新(我正在进行 debian 测试)之后,我开始收到此错误(即使是我标记的修订版并且几天前工作正常)。

答:

163赞 Yu Hao 7/21/2013 #1

不要在标头中定义变量。将声明放在标头中,将定义放在其中一个 .c 文件中。

在 config.h 中

extern const char *names[];

在某些 .c 文件中:

const char *names[] = { 
  "brian", "stefan", "steve" };

如果将全局变量的定义放在头文件中,则此定义将转到包含此标头的每个 .c 文件,并且您将收到多个定义错误,因为可变变量可以多次声明,但只能定义一次。

此外,如果必须在头文件中定义变量,则可以使用关键字,还可以做另一件事。static

static const char *names[] = {
  "brian", "stefan", "steve" };

这样,变量将在整个程序中只定义一次,并且可以多次访问。names

评论

1赞 mazix 7/21/2013
解决!:)你能告诉我为什么我不应该把声明放在文件中吗?h*.
7赞 Jiminion 7/21/2013
所以它不会这样做。仅使用 *.h 文件来引用信息。您必须记住,“include”意味着它包含该文件中的所有 *.h 信息,因此您将使用 *.h 将该信息(而不仅仅是引用)复制到每个文件中。这可能会让链接者感到困惑,而且确实如此。
4赞 Yu Hao 7/21/2013
@mazix 否,全局变量的定义应该转到 .c 文件,并将声明放在标头中。请记住,您可以多次声明可变变量,但只能定义一次。
1赞 Spalteer 7/21/2013
只是为了使解释稍微清楚一点,头文件可能包含在多个 c 文件中,因此您最终会得到具有相同名称的变量的多个声明
0赞 Ebrahim Karimi 10/28/2018
是否可以用于类构造函数?extern
52赞 JonathanWhittenberg 8/16/2014 #2

公共函数的声明在头文件中,是的,但定义在头文件中也是绝对有效的!如果在实用程序函数的标头中定义不希望在每个 c 文件中再次定义的内容,则可以将定义声明为静态(整个程序只允许 1 个副本)。即定义一个枚举和一个静态函数来将枚举转换为字符串。然后,您不必为每个包含标头的 .c 文件将枚举重写为字符串转换器。:)

评论

4赞 Saik 5/28/2017
实际上,我发现这个答案比顶部答案方便得多。例如,只有一个标头来存储所有全局变量,而不是 .h 和 .cpp 文件,这更方便和有吸引力。谢谢。
0赞 Alejandro Galera 5/3/2018
我认为这个解决方案也比投票最多的解决方案更好,因为另一个需要在每个 *.c 文件中定义值,而且您的@JonathanWhittenberg看起来更优雅。多谢
1赞 SimonC 1/9/2019
比 AA 更好、更优雅的解决方案。+1 添加为什么这并不总是一个坏主意。
9赞 PPenguin 6/8/2019
这并不是对静态作用的准确描述。“您可以将定义声明为静态(整个程序只允许 1 个副本)”不!static 使定义范围限定为该编译单元。因此,它为每个编译单元提供一个副本。因此,如果你有一些大的字符串列表,你的程序最终将有许多重复的副本。每个 C 文件一个。如果稍后进行调试,则对于静态函数来说,情况会更糟,因为不再有单个函数可以放置断点,而是在生成的链接程序中该函数的许多副本。
0赞 Phrunsys Emmason 2/7/2022 #3

使定义在头文件中保持静态。

评论

1赞 Community 2/7/2022
您的答案可以通过额外的支持信息得到改进。请编辑以添加更多详细信息,例如引文或文档,以便其他人可以确认您的答案是正确的。您可以在帮助中心找到有关如何写出好答案的更多信息。