Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
196 views
in Technique[技术] by (71.8m points)

c++ - At what exact moment is a local variable allocated storage?

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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...