开发者

Allocation of String on the stack

开发者 https://www.devze.com 2023-01-26 15:23 出处:网络
I am allocating 12 char string on the st开发者_开发技巧ack, or equivalently it is 12 bytes. Dissembling with gdb (under Linux) reveals that to allocate space for string on the stack, esp is moved by

I am allocating 12 char string on the st开发者_开发技巧ack, or equivalently it is 12 bytes.

Dissembling with gdb (under Linux) reveals that to allocate space for string on the stack, esp is moved by -24 (down the stack).

push   %ebp
mov    %esp,%ebp
sub    $0x18,%esp

Why is it moved by 24 (0x18)?


Some of it could be space for outgoing parameters, if your function calls others; some of it could be temporary space for values spilled out of registers; some of it could be padding. It will be very dependent on compiler version and optimisation flags.

Here's some simple nonsense code for illustration:

extern int foo(int a, int b);

int bar(int c)
{
    char s[12];

    s[0] = foo(c, 123);
    return 456;
}

Here it is compiled with no optimisation using gcc 4.3.2 on a Debian Lenny machine:

bar:
    pushl   %ebp
    movl    %esp, %ebp
    subl    $24, %esp
    movl    $123, 4(%esp)
    movl    8(%ebp), %eax
    movl    %eax, (%esp)
    call    foo
    movb    %al, -12(%ebp)
    movl    $456, %eax
    leave
    ret

Like your code, it's allocating 24 bytes. Here's what they're used for:

     Stack while running bar()
    :                         :
    +-------------------------+
    | incoming parameter: c   | 8(%ebp)
    +-------------------------+            ---
    | return address          | 4(%ebp)     ^
    +-------------------------+             |
    | old %ebp                | (%ebp)      |
    +-------------------------+             |  bar()'s stack
    | s[8]..s[11]             | -4(%ebp)    | frame: 32 bytes
    +-------------------------+             |
    | s[4]..s[7]              | -8(%ebp)    |
    +-------------------------+             |
    | s[0]..s[3]              | -12(%ebp)   |
    +-------------------------+             |     Stack while running foo()
    | (unused)                | 8(%esp)     |    :                         :
    +-------------------------+             |    +-------------------------+
    | outgoing parameter: 123 | 4(%esp)     |    | incoming parameter: b   |
    +-------------------------+             |    +-------------------------+
    | outgoing parameter: c   | (%esp)      v    | incoming parameter: a   |
    +-------------------------+            ---   +-------------------------+
                                                 | return address          |
                                                 +-------------------------+
                                                 | old %ebp                |
                                                 +-------------------------+
                                                 : locals for foo()        :

A bit of experiment will show that if s[] is increased, it will eat into the unused space; e.g. if it is 13 bytes, the stack frame is the same size, but s[] will start one byte earlier (at -13(%ebp)) - up to 16 bytes, where all of the allocated stack will actually be used. If s is declared as s[17], the compiler will allocate 40 bytes of stack instead of 24.

This is because the compiler is keeping the total size of the stack frame (everything on the left of the above diagram, except the incoming parameter, which is really at the bottom of the caller's stack frame) rounded up to a multiple of 16 bytes. (See the gcc documentation for the -mpreferred-stack-boundary option.)


Because other things besides your string are getting stored on the stack, such as other local variables or temporaries. When you have complicated expressions, the compiler stores sometimes stores intermediate results of those expressions in memory on the stack (especially when optimization is disabled), even if they don't correspond to explicit local variables.

0

精彩评论

暂无评论...
验证码 换一张
取 消