C ld与全局变量的链接时错误

时间:2015-04-06 12:47:21

标签: c linker ld

我正在阅读计算机系统:程序员的观点,我遇到了以下C文件:

foo.c的:

void f(void);

int x = 15213;
int y = 15212;

int main()
{
    f();
    printf("x = 0x%x y = 0x%x \n", x, y);
    return 0;
}

Bar.c:

double x;
void f()
{
    x = -0.0;
}

使用gcc -o foobar foo.c bar.c编译并提供以下输出:

 x = 0x0 y = 0x80000000

哇。因此,int是4个字节,double是8个字节(无论如何在我的系统上),并且x的强符号在Foo.c中,x被赋予-0.0的十六进制表示,这反过来也会覆盖y!

所以我想了解更多相关信息。为什么标准C型保护措施不会在这里发挥作用?将0x0000000080000000盲目地写入ELF中存储的x,并且y恰好在它旁边并被覆盖?随意尽可能详细。

2 个答案:

答案 0 :(得分:1)

您违反了" 一个定义规则"

  

外部定义是外部声明,也是一个   函数的定义(内联定义除外)或   宾语。如果使用外部链接声明的标识符   表达式(除了作为sizeof或_Alignof的操作数的一部分   运算符,其结果是整数常量),在整个某处   程序应该只有一个外部定义   标识符;否则,不得超过一个。

导致未定义的行为。基本上,对象x有2个定义,声明也各不相同。标准说明

  

引用同一对象或函数的所有声明都应具有   兼容型;否则,行为未定义。

注意: %x用于以无符号十六进制格式打印出unsigned int,并尝试使用%x打印出一个负数导致未定义的行为。

使用错误的格式说明符会导致未定义的行为。

答案 1 :(得分:1)

您是否注意到编译时会出现此警告。

  

/ usr / bin / ld:警告:符号`x'的对齐4 in /tmp/cciNZgVG.o在/tmp/cc8pYw6O.o中小于8

这是未定义的行为。不要忽视这些警告。它根据您指定的值产生答案。