为什么编译器在堆栈中分配的数量超过了需要?

我有一个简单的C程序。 比方说,我有一个长度为20的int和一个char数组。我总共需要24个字节。

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

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

 ..\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" 

这是为什么? 当我编程程序集时,我总是只保留我需要的最小内存而没有任何问题。 这是编译器的限制,它无法评估所需的内存,或者有这样的原因吗?

这是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) 

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

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

正如VermillionAzure在评论中指出的那样 ,你应该提供你的gcc版本和编译时选项(使用gcc -v来显示这些)。

因为您尚未启用优化。

如果没有优化,编译器不会尝试最小化生成代码中任何内容所需的空间或时间 – 它只是以最直接的方式生成代码。

如果希望编译器生成合适的代码,请添加-O2 (甚至只是-O1 )或-Os

我总共需要24个字节。

编译器需要空间用于返回地址和基指针。 当你处于64位模式时,那是另外16个字节。 总计40.将该数据舍入到32字节边界,得到64。