在什么确切的时刻是一个局部变量分配的存储? [英] At what exact moment is a local variable allocated storage?

查看:141
本文介绍了在什么确切的时刻是一个局部变量分配的存储?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我们有以下:

  void print()
{
int a; // declaration
a = 9;
cout<< a<< endl;
}

int main()
{
print();
}

在main函数打印时调用的变量a的存储或者是当执行到达函数内部的声明时?

解决方案

这是非常依赖于编译器的,但在逻辑上,存储是在变量被声明时分配的。 / p>

考虑这个简单的C ++示例:

  // junk.c ++ 
int addtwo(int a)
{
int x = 2;

return a + x;
}

当GCC编译此代码时,会生成以下代码(; comments ):

  .filejunk.c ++
.text
.globl _Z6addtwoi
.type _Z6addtwoi,@function
_Z6addtwoi:
.LFB2:
pushl%ebp;存储旧的堆栈帧(调用者的参数和本地)
.LCFI0:
movl%esp,%ebp;为我们的参数和局部变量设置基本指针
.LCFI1:
subl $ 16,%esp;为堆栈中的局部变量留出空间
.LCFI2:
movl $ 2,-4(%ebp);将2存储在x(从基指针偏移-4)
movl -4(%ebp),%edx; put x写入DX寄存器
movl 8(%ebp),%eax;将a(从基本指针偏移+8)写入AX寄存器
addl%edx,%eax; ,将结果存储在AX
中;删除堆栈框架,不再有局部变量或参数
ret;退出函数,结果按照约定在AX中返回
.LFE2:
.size _Z6addtwoi,。-_ Z6addtwoi
.identGCC:(Ubuntu 4.3.3-5ubuntu4)4.3.3
.section .note.GNU-stack,@ progbits

_Z6addtwoi和.LCFI2之间的所有内容都是样板代码,用于设置堆栈框架(存储上一个函数的变量等)安全地阻止)。最后一个subl $ 16,%esp是局部变量x的分配。



.LCFI2是你键入的实际执行代码的第一位。 movl $ 2,-4(%ebp)将值2放入变量。 (换句话说,初始化)现在你的空间被分配和初始化。然后,将值装载到寄存器EDX中,然后将8(%ebp)中的参数移动到另一个寄存器EAX中。然后将它们加在一起,将结果留在EAX中。这是你实际键入的任何代码的结束。其余的再次只是样板。由于GCC要求在EAX中返回整数,因此不必对返回值进行任何操作。 leave指令将栈框架下拉,ret指令将控制权返回给调用者。



TL; DR总结:已经分配了你的块中的第一行可执行代码(配对{})。






d清理这一点有解释性评论看到这是所选择的答案。


Suppose we have the following:

void print()
{
     int a;  // declaration
     a = 9;
     cout << a << endl;
}

int main ()
{
     print();
}

Is the storage for variable a allocated at the moment function print is called in main or is it when execution reaches the declaration inside the function?

解决方案

This is very much compiler dependent under the covers, but logically the storage is assigned as soon as the variable is declared.

Consider this simplistic C++ example:

// junk.c++
int addtwo(int a)
{
    int x = 2;

    return a + x;
}

When GCC compiles this, the following code is generated (; comments mine):

.file   "junk.c++"
    .text
.globl _Z6addtwoi
    .type   _Z6addtwoi, @function
_Z6addtwoi:
.LFB2:
    pushl   %ebp           ;store the old stack frame (caller's parameters and locals)
.LCFI0:
    movl    %esp, %ebp     ;set up the base pointer for our parameters and locals
.LCFI1:
    subl    $16, %esp      ;leave room for local variables on the stack
.LCFI2:
    movl    $2, -4(%ebp)   ;store the 2 in "x" (-4 offset from the base pointer)
    movl    -4(%ebp), %edx ;put "x" into the DX register
    movl    8(%ebp), %eax  ;put "a" (+8 offset from base pointer) into AX register
    addl    %edx, %eax     ;add the two together, storing the results in AX
    leave                  ;tear down the stack frame, no more locals or parameters
    ret                    ;exit the function, result is returned in AX by convention
.LFE2:
    .size   _Z6addtwoi, .-_Z6addtwoi
    .ident  "GCC: (Ubuntu 4.3.3-5ubuntu4) 4.3.3"
    .section    .note.GNU-stack,"",@progbits

Everything between _Z6addtwoi and .LCFI2 is boilerplate code used to set up the stack frame (store the previous function's variables, etc. safely out of the way). That last "subl $16, %esp" is the allocation of the local variable x.

.LCFI2 is the first bit of actual executing code that you've typed. "movl $2, -4(%ebp)" is putting the value 2 into the variable. (Initialization, in other words.) Now your space is allocated AND initialized. After that it loads the value into register EDX and follows that by moving your parameter, found in "8(%ebp)", into another register EAX. It then adds the two together, leaving the result in EAX. This is now the end of any code you've actually typed. The rest is again just boilerplate. Since GCC mandates that integers are returned in EAX, no work has to be done for the return value. The "leave" instruction tears down the stack frame and the "ret" instruction returns control back to the caller.

TL;DR summary: you can think of your space as having been allocated with the very first line of executable code in your block (paired {}).


I thought I'd clean this up a bit with explanatory comments seeing as this is the selected answer.

这篇关于在什么确切的时刻是一个局部变量分配的存储?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆