为什么编译器在堆栈中分配的空间超出了需要? [英] Why does the compiler allocate more than needed in the stack?

查看:118
本文介绍了为什么编译器在堆栈中分配的空间超出了需要?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个简单的C程序.例如,假设我有一个int和一个长度为20的char数组.我总共需要24个字节.

I have a simple C program. Let's say, for example, I have an int and a char array of length 20. I need 24 bytes in total.

int main()
{
   char buffer[20];
   int x = 0;
   buffer[0] = 'a';
   buffer[19] = 'a';
}

堆栈需要对齐到16个字节的边界,因此我认为编译器将保留32个字节.但是,当我使用gcc x86-64编译这样的程序并读取输出程序集时,编译器会保留64个字节.

The stack needs to be aligned to a 16 bytes boundary, so I presume a compiler will reserve 32 bytes. But when I compile such a program with gcc x86-64 and read the output assembly, the compiler reserves 64 bytes.

..\gcc -S -o main.s main.c

给我:

    .file   "main.c"
    .def    __main; .scl    2;  .type   32; .endef
    .text
    .globl  main
    .def    main;   .scl    2;  .type   32; .endef
    .seh_proc   main
main:
    pushq   %rbp                        # RBP is pushed, so no need to reserve more for it
    .seh_pushreg    %rbp
    movq    %rsp, %rbp
    .seh_setframe   %rbp, 0
    subq    $64, %rsp                   # Reserving the 64 bytes
    .seh_stackalloc 64
    .seh_endprologue
    call    __main
    movl    $0, -4(%rbp)                # Using the first 4 bytes to store the int
    movb    $97, -32(%rbp)              # Using from RBP-32 
    movb    $97, -13(%rbp)              # to RBP-13 to store the char array
    movl    $0, %eax
    addq    $64, %rsp                   # Restoring the stack with the last 32 bytes unused
    popq    %rbp
    ret
    .seh_endproc
    .ident  "GCC: (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 5.2.0"

那是为什么?当我编写汇编程序时,我总是只保留所需的最小内存,没有任何问题.难道是编译器无法评估所需内存的限制,还是有原因吗?

Why is that? When I program assembly, I always reserve only the minimum memory I need without any problem. Is that a limitation of the compiler which has trouble evaluating the needed memory or is there a reason for that?

这是gcc -v

Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=D:/Mingw64/bin/../libexec/gcc/x86_64-w64-mingw32/5.2.0/lto-wrapper.exe
Target: x86_64-w64-mingw32
Configured with: ../../../src/gcc-5.2.0/configure --host=x86_64-w64-mingw32 --build=x86_64-w64-mingw32 --target=x86_64-w64-mingw32 --prefix=/mingw64 --with-sysroot=/c/mingw520/x86_64-520-posix-seh-rt_v4-rev0/mingw64 --with-gxx-include-dir=/mingw64/x86_64-w64-mingw32/include/c++ --enable-shared --enable-static --disable-multilib --enable-languages=c,c++,fortran,objc,obj-c++,lto --enable-libstdcxx-time=yes --enable-threads=posix --enable-libgomp --enable-libatomic --enable-lto --enable-graphite --enable-checking=release --enable-fully-dynamic-string --enable-version-specific-runtime-libs --disable-isl-version-check --disable-libstdcxx-pch --disable-libstdcxx-debug --enable-bootstrap --disable-rpath --disable-win32-registry --disable-nls --disable-werror --disable-symvers --with-gnu-as --with-gnu-ld --with-arch=nocona --with-tune=core2 --with-libiconv --with-system-zlib --with-gmp=/c/mingw520/prerequisites/x86_64-w64-mingw32-static --with-mpfr=/c/mingw520/prerequisites/x86_64-w64-mingw32-static --with-mpc=/c/mingw520/prerequisites/x86_64-w64-mingw32-static --with-isl=/c/mingw520/prerequisites/x86_64-w64-mingw32-static --with-pkgversion='x86_64-posix-seh-rev0, Built by MinGW-W64 project' --with-bugurl=http://sourceforge.net/projects/mingw-w64 CFLAGS='-O2 -pipe -I/c/mingw520/x86_64-520-posix-seh-rt_v4-rev0/mingw64/opt/include -I/c/mingw520/prerequisites/x86_64-zlib-static/include -I/c/mingw520/prerequisites/x86_64-w64-mingw32-static/include' CXXFLAGS='-O2 -pipe -I/c/mingw520/x86_64-520-posix-seh-rt_v4-rev0/mingw64/opt/include -I/c/mingw520/prerequisites/x86_64-zlib-static/include -I/c/mingw520/prerequisites/x86_64-w64-mingw32-static/include' CPPFLAGS= LDFLAGS='-pipe -L/c/mingw520/x86_64-520-posix-seh-rt_v4-rev0/mingw64/opt/lib -L/c/mingw520/prerequisites/x86_64-zlib-static/lib -L/c/mingw520/prerequisites/x86_64-w64-mingw32-static/lib '
Thread model: posix
gcc version 5.2.0 (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 

推荐答案

编译器确实可以为自己保留额外的内存.

Compilers may indeed reserve additional memory for themselves.

Gcc具有标志-mpreferred-stack-boundary,用于设置它将保持的对齐方式.根据文档 ,默认值为4,这应产生16字节对齐,这是SSE指令所需的.

Gcc has a flag, -mpreferred-stack-boundary, to set the alignment it will maintain. According to the documentation, the default is 4, which should produce 16-byte alignment, which needed for SSE instructions.

VermillionAzure在注释,则应提供您的gcc版本和编译时选项(使用gcc -v进行显示).

As VermillionAzure noted in a comment, you should provide your gcc version and compile-time options (use gcc -v to show these).

这篇关于为什么编译器在堆栈中分配的空间超出了需要?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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