链接 C 时出现"Multiple definition"错误,但仅在 MinGW 上



我有一些代码,当我在Linux上编译时,运行良好,但在MinGW for Windows上失败。

我正在把这四份文件汇编在一起。a.h是头文件,b.cc.cmain.c。内容如下。

└──> cat a.h
enum {
BLACK,
WHITE
} Colors;
└──> cat b.c
#include "a.h"
#include <stdio.h>
void foo() {
printf("%dn", BLACK);
}
└──> cat c.c
#include "a.h"
#include <stdio.h>
void bar() {
printf("%dn", WHITE);
}
└──> cat main.c
void foo();
void bar();
int main() {
foo();
bar();
return 0;
}

我用这个命令编译它们:

gcc -c b.c; gcc -c c.c; gcc -c main.c; gcc -o colors b.o c.o main.o

它在我的Linux桌面上运行良好,但在MinGW虚拟机上失败了。错误为:

# gcc -c b.c; gcc -c c.c; gcc -c main.c; gcc -o colors b.o c.o main.o
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: c.o:c.c:(.bss+0x0): multiple definition of `Colors'; b.o:b.c:(.bss+0x0): first defined here
collect2.exe: error: ld returned 1 exit status

当我在Linux上的b.o上运行nm时,我看到的是:

└──> nm b.o
0000000000000004 C Colors
0000000000000000 T foo
U printf

但在MinGW上,我看到的是:

0000000000000004 B Colors

不知怎的,gcc在每个系统上都以不同的方式编译它们。这里的B意味着我不能有两次相同的符号,尽管在Linux上我得到了C,它工作得很好。来自nm:的手册页

"B"
"b" The symbol is in the uninitialized data section (known as BSS).
"C" The symbol is common.  Common symbols are uninitialized data.  When linking, multiple common symbols may appear with
the same name.  If the symbol is defined anywhere, the common symbols are treated as undefined references.

我该如何解决这个问题,以便能够在MinGW上进行编译?

Linux使用GCC 9;MinGW可能使用GCC 10。

您似乎创建了一个名为Colors的未标记enum类型的变量:

enum {
BLACK,
WHITE
} Colors;

其中您可能只想声明一个带有标记Colors:的enum类型

enum Colors {
BLACK,
WHITE
};

如果前者包含在多个源文件中,则前者是无效的C,因为它生成了Colors的重复定义。这是允许的,但不要求产生错误;不同系统的对象文件格式如何表示未初始化的全局变量的实现细节会导致它在链接时被检测为错误。现代GCC不再使用commons,即使在支持它们的目标上也是如此,所以如果您更新到足够新的GCC,这在Linux上也是一个错误。

最新更新