"Multiple definition" 链接 C 时出错但仅在 MinGW 上
"Multiple definition" error when linking C but only on MinGW
我有一些代码,当我在 Linux 上编译时,它工作正常,但在 Windows 的 MinGW 上失败。
我正在一起编译这四个文件。 a.h
是头文件,b.c
、c.c
和main.c
。内容如下。
└──> cat a.h
enum {
BLACK,
WHITE
} Colors;
└──> cat b.c
#include "a.h"
#include <stdio.h>
void foo() {
printf("%d\n", BLACK);
}
└──> cat c.c
#include "a.h"
#include <stdio.h>
void bar() {
printf("%d\n", 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
当我 运行 nm
在 b.o
上 Linux 时,我看到了这个:
└──> 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
的重复定义。这是允许的,但不是产生错误所必需的;不同系统的目标文件格式如何表示未初始化的全局变量的实现细节导致它在 link 时间被或不被检测为错误。现代 GCC 即使在支持它们的目标上也不再使用公用资源,因此如果您更新到足够新的 GCC,这也会在 Linux 上出现错误。
我有一些代码,当我在 Linux 上编译时,它工作正常,但在 Windows 的 MinGW 上失败。
我正在一起编译这四个文件。 a.h
是头文件,b.c
、c.c
和main.c
。内容如下。
└──> cat a.h
enum {
BLACK,
WHITE
} Colors;
└──> cat b.c
#include "a.h"
#include <stdio.h>
void foo() {
printf("%d\n", BLACK);
}
└──> cat c.c
#include "a.h"
#include <stdio.h>
void bar() {
printf("%d\n", 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
当我 运行 nm
在 b.o
上 Linux 时,我看到了这个:
└──> 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
的重复定义。这是允许的,但不是产生错误所必需的;不同系统的目标文件格式如何表示未初始化的全局变量的实现细节导致它在 link 时间被或不被检测为错误。现代 GCC 即使在支持它们的目标上也不再使用公用资源,因此如果您更新到足够新的 GCC,这也会在 Linux 上出现错误。