首页 > 解决方案 > C 代码的混淆行为与阴影结构声明

问题描述

考虑以下 C 代码:

#include <stdio.h>

typedef struct {
    int a;
} TestType;

int main(){
    int an_int;
    TestType test;
    // printf("%d\n",test.a);
    {
        TestType test;
        test.a = 777;
        printf("offset: %lld\n", &test.a - &an_int); // maybe 2?
    }
    printf("%d\n", test.a);                        // should be garbage
    printf("offset: %lld\n", &test.a - &an_int);     // maybe 1?    
}

我声明 a TestType test,然后启动一个范围并TestType test首先声明另一个阴影。最后打印语句的预期输出是堆栈上的任何内容。编译gcc -o stack-allocate-weird stack-allocate-weird.c并运行,我得到输出:

offset: 1
777
offset: 1

所以这两个位置是一样的。此外,valgrind ./stack-allocate-weird报告没有错误。取消注释第一个打印语句给了我预期的输出:

-771776240
offset: 2
-771776240
offset: 1

如果不是struct TestType我只声明一个int,则代码的行为符合预期(最后一个打印语句打印垃圾)。

我将代码放到服务器上并编译它并得到:

offset: -2
0
offset: -1

哪个看起来也不错(我猜堆栈的方向相反?)。另一方面,将在我的计算机上编译的二进制文件移到服务器上会产生原始的错误输出:

offset: 1
777
offset: 1 

这是 gcc 的已知错误吗?

gcc -v在我的电脑上说(一堆其他的东西和):

gcc version 7.4.0 (Ubuntu 7.4.0-1ubuntu1~18.04)    

在服务器上它说:

gcc version 8.3.1 20190223 (Red Hat 8.3.1-2) (GCC)

所以也许这在两者之间得到了解决?

标签: ccallstackshadowing

解决方案


我认为这不是 GCC 的错误。编译器会延迟外部的分配,TestType test直到需要它为止。这是在第printf()16 行的第二个。内部TestType test被放置在偏移量 1 处,就像你看到的那样,直到它的范围关闭并且它的内存再次空闲。现在需要外部的并占用相同的空间,为您提供内部的值和相同的偏移量。


推荐阅读