我在Ubuntu 22.04上得到了“多个定义”错误,虽然我在Ubuntu 20.04上没有得到这样的错误。我把包含守卫放在头文件的顶部,但它不起作用。有谁知道除了降级到Ubuntu 20.04之外如何解决这个问题吗?
我有这三个文件
global.h
#ifndef GLOBAL_H
#define GLOBAL_H
int a;
int b;
#endif
a.c
#include "global.h"
#include <stdio.h>
#include<unistd.h>
void defb(void);
int main(int argc, char **argv)
{
defb();
a = 1;
printf("a=%d\n",a);
return 0;
}
B.c
#include "global.h"
#include <stdio.h>
#include<unistd.h>
void defb()
{
b = 2;
printf("b=%d\n",b);
}
我用gcc编译了
gcc -O a.c b.c
然后我得到了下面的错误
/usr/bin/ld: /tmp/ccOgmibV.o:(.bss+0x0): multiple definition of `b'; /tmp/ccsYu4Ch.o:(.bss+0x0): first defined here
/usr/bin/ld: /tmp/ccOgmibV.o:(.bss+0x4): multiple definition of `a'; /tmp/ccsYu4Ch.o:(.bss+0x4): first defined here
collect2: error: ld returned 1 exit status
如何解决这个问题?提前谢谢你。
1条答案
按热度按时间c9x0cxw01#
GCC的默认行为在版本10中改变了。您可以通过将开关
-fcommon
添加到编译选项来获得旧的行为。在函数之外,
int a;
是一个 * 临时定义 *。尽管它的名字,它实际上不是一个定义。但是,如果翻译单元中没有标识符的定义,则临时定义的存在将导致创建一个定义。当一个标识符的临时定义或定义出现在包含在多个转换单元中的头文件中时,会导致该标识符有多个定义。C标准不定义标识符有多个定义时的行为。
在版本10之前,GCC的默认行为是将由临时定义产生的定义标记为“公共”符号,而Unix链接器将“公共”符号的多个定义合并为单个定义,并且不会为其生成错误消息。在版本10中,GCC的默认行为更改为将由临时定义产生的定义标记为普通符号,并且连接器将普通符号的多个定义视为错误。
在编译时使用
-fcommon
会请求旧的行为。您也可以通过插入
extern
将临时定义更改为普通声明。将int a;
更改为extern int a;
将使其成为不是临时定义的普通声明,因此不会导致创建定义。如果进行此更改,你需要确保每个这样的符号都有一个定义存在于源文件中。所以如果int a;
不存在的话,你需要将它添加到一个源文件中。更多的信息在这个答案和这个。