5

首先,请帮助我找到一个更准确地描述情况的更好的标题。我创建了以下在调试实际(嵌入式)代码时偶然发现的问题的简化版本。

考虑以下文件代码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)发出警告吗?

这是一个错误吗?

4

2 回答 2

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 允许任何实现在存在这样的程序时停止翻译,所以除非你有充分的理由这样做,否则你应该避免它。

于 2013-06-28T19:43:59.197 回答
1

为了摆脱@ouah的回答,我认为它只是一个警告的原因是因为它是一个未初始化的变量,所以它在该.bss部分中。通过初始化变量,编译器将它们移动到该部分 - 但是,重叠只是一个警告.data的事实可能是 gcc 的怪癖。.bss

于 2013-06-28T19:49:31.970 回答