【问题标题】:C ld link-time error with global variables带有全局变量的 C ld 链接时错误
【发布时间】:2021-12-24 01:05:23
【问题描述】:

我正在阅读 Computer Systems: A Programmer's Perspective,我遇到了以下 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 是否盲目地写入了 x 存储在 ELF 中的位置,而 y 恰好在它旁边并被覆盖?尽可能详细。

【问题讨论】:

    标签: c linker ld


    【解决方案1】:

    你有没有注意到在你编译的时候会出现这个警告。

    /usr/bin/ld:警告:/tmp/cciNZgVG.o 中符号“x”的对齐 4 小于 /tmp/cc8pYw6O.o.o 中的 8

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

    【讨论】:

      【解决方案2】:

      你违反了“一个定义规则

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

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

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

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

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

      【讨论】:

      • %x 用于显示组成 x 和 y 的字节。关键是 y 被覆盖了。尝试使用 %d 或其他。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多