【问题标题】:Two local variables of the same program running on two VPS have different address order? [duplicate]两个VPS上运行的同一个程序的两个局部变量有不同的地址顺序? [复制]
【发布时间】:2019-03-26 03:36:32
【问题描述】:

我有两个 AWS lightail vps 盒子,我正在两个 vps 上尝试以下简单的 C 程序来测试局部变量的地址。

#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[])
{
        int value = 5;
        char buffer_one[8], buffer_two[8];

        strcpy(buffer_one, "one");
        strcpy(buffer_two, "two");

        printf("buffer_one is at %p\n", buffer_one);
        printf("buffer_two is at %p\n", buffer_two);

        return 0;
}

在盒子 A(运行 ubuntu 14.04)上,它会产生如下内容:

buffer_one is at 0x7ffd1fe3d5a0
buffer_two is at 0x7ffd1fe3d5b0

在框 B 上(运行 Centos 7.5,如下:

buffer_one is at 0x7fffa53678a0
buffer_two is at 0x7fffa5367890

我很惊讶,因为这两个变量都在主函数中,这使得它们成为局部变量,因此它们应该在运行时存储在程序地址空间的“堆栈”中。如果是这样,第一个变量(buffer_one)应该在一个比第二个变量(buffer_two)“更高”的地址。 B确实是这样,但是为什么A是相反的……?

【问题讨论】:

  • 副本要求同一程序中不同功能的不同布局,但答案与理解为什么在不同甚至相同的编译器上可能重新排序有关。
  • 好的编译器不会盲目地读取声明并按照对象在程序中出现的顺序在堆栈上分配空间。优秀的编译器会阅读所有源代码并寻求最佳代码和安排。这可能包括按大小对对象进行分组以最小化对齐所需的填充,并且可能包括在不同的时间为不同的对象使用相同的空间。

标签: c memory-address


【解决方案1】:

除了 Elbek 的回答,我想补充一点原因。

编译器只确保局部变量在堆栈上。 它的工作只是确保最终程序按照您对源代码的期望执行。

因此不能保证实际的布局和顺序,因为它们不会影响正常程序的行为。 它们取决于编译器的实现。

编译器可能正在做一些优化,或者可能正在使用不同的指令生成技术。所有这些都可能影响局部变量的布局(即实际位置)。

这就是为什么不同的编译器,甚至同一个编译器的不同版本,会产生不同的结果。

【讨论】:

    【解决方案2】:

    在两台机器上检查您的 gcc 版本。可能是因为版本不同。

    ubuntu 14.04 可能有 gcc-4.8 (>= 4.8.2-5~)

    centos 7.5 可能有 gcc (GCC) 4.8.2 20140120 (Red Hat 4.8.2-16)

    一个小的区别。不过可能是这个原因

    【讨论】:

    • 感谢您的回答,在我的情况下,ubuntu box(A) 有 4.8.4,而 centos(B) 有 4.8.5。对我来说,这似乎是一个小的版本差异......
    猜你喜欢
    • 1970-01-01
    • 2019-06-22
    • 2020-10-13
    • 1970-01-01
    • 2013-10-23
    • 1970-01-01
    • 1970-01-01
    • 2015-02-10
    • 1970-01-01
    相关资源
    最近更新 更多