首先,请帮助我找到一个更准确描述情况的更好的标题。我在调试真实世界(嵌入式)代码时创建了以下简要版本的问题。
考虑以下文件t1.c
的代码:
#include <stdio.h>
int A;
void f() { printf("%d\n", A); }
extern void g();
void main(void)
{
g(); A=1; g();
A++;
f();
}
以及t2.c
的代码:
#include <stdio.h>
double A;
void g()
{
A += 1.0;
printf("%f\n", A);
}
现在编译并运行如下代码:
gcc -Wall t1.c t2.c -o t && ./t
给出
1.000000
2.000000
1
请注意,这两个文件都包含一个全局变量调用A
,它具有不同的类型。我期望链接错误,因为符号A存在多次。
当我初始化两个变量中的一个时,我实际上得到了一个链接警告(对象大小在不同的.o 中的变化),当我初始化时出现错误(多个定义)他们两个。
我用gcc 4.7和4.4尝试过这个。
这是预期的行为吗?如果是这样,有什么我可以做的来指示工具链(基于gcc)来警告它吗?
这是一个错误吗?
答案 0 :(得分:4)
是,使用-fno-common
选项进行编译以获取链接器错误:
$ gcc -Wall -fno-common -c t1.c
$ gcc -Wall -fno-common -c t2.c
$ gcc t1.o t2.o -o t
t2.o:t2.c:(.bss+0x0): multiple definition of `_A'
t1.o:t1.c:(.bss+0x0): first defined here
collect2: error: ld returned 1 exit status
$
如果你想在一行中编译它,你也可以将--warn-common
传递给链接器(这里带有--fatal-warnings
以产生错误而不是警告):
$ gcc -Wl,--fatal-warnings,--warn-common -Wall t1.c t2.c -o t
/tmp/cc1xQo79.o: warning: common of `_A' overriding smaller common
/tmp/ccLnhxoe.o: warning: smaller common is here
collect2: error: ld returned 1 exit status
$
默认情况下,gcc
执行C未定义行为的各种优化作为扩展。 C允许任何实现在这样的程序出现时停止翻译,所以除非你有充分的理由去做,否则你应该避免它。
答案 1 :(得分:1)
关于@ ouah的答案,我认为它只是一个警告的原因是因为它是一个未初始化的变量,所以它进入.bss
部分。通过初始化变量,编译器将它们移动到.data
部分 - .bss
重叠只是一个警告的事实可能是gcc怪癖。