理解C中的堆栈帧

时间:2014-04-25 05:27:15

标签: c gcc gdb memory-layout

我试图理解C中的堆栈帧,所以我写了一个简单的C代码来分析堆栈帧。

  • 首先,fun1()返回一个局部变量的地址,该地址变量初始化为10到ptr,这会导致警告,但是没问题......如果我打印* ptr的值现在它打印10,即使那很好......

  • 接下来fun2()返回一个甚至没有初始化的局部变量的地址,如果我尝试打印* ptr的值,无论我是否返回一个地址,它都会打印10或者b ...

  • 为了理解这里发生了什么,我使用了gdb。 使用gdb,我开始逐步调试,当我到达线路时,返回& a "在fun2()中,我尝试打印b的地址, print& b 但是它打印出来了 无法获取" b"的地址这不是一个左值。

我不明白,当我尝试打印a,打印& a 的地址时,它打印得非常好,为什么不打印b的地址。 *当a为什么时,为什么不是左值?

# include <stdio.h>

int * fun1() {
    int a = 10; 
    return &a; 
}

int * fun2()
{
    int a;
    int b;
    return &a;           // return &b;
}

int main ()  
{
    int *ptr;
    ptr = fun1();
    ptr = fun2();
    printf ("*ptr = %d, fun2() called...\n", *ptr);
    return 0;
}

2 个答案:

答案 0 :(得分:3)

编译器正在优化fun2中的一些代码。

如果您返回&a,则会优化int b;。如果您返回&b,则会优化int a;。如果添加一些虚拟计算,您将看到返回值的地址不同。

int * fun2()
{
    int a;
    int b;
    int* p = &a;
    p = &b;
    return p;
}

更改main以打印fun1fun2的返回值。

int main ()  
{
    int *ptr;
    ptr = fun1();
    printf ("ptr = %p, fun1() called...\n", ptr);
    ptr = fun2();
    printf ("ptr = %p, fun2() called...\n", ptr);
    printf ("*ptr = %d, fun2() called...\n", *ptr);
    return 0;
}

当我运行此代码时,我得到以下示例输出:

ptr = 0x7ffff98c70ec, fun1() called...
ptr = 0x7ffff98c70e4, fun2() called...
*ptr = 32749, fun2() called...

答案 1 :(得分:0)

在将地址返回到b时,它为我编译就好了。但是你不应该返回局部变量的地址。 Check out this link