¿Por qué el compilador asigna más de lo necesario en la pila?




memory compiler-construction (2)

Necesito 24 bytes en total.

El compilador necesita espacio para una dirección de retorno y un puntero base. Como está en modo de 64 bits, eso es otros 16 bytes. Total 40. Redondea eso hasta un límite de 32 bytes y obtienes 64.

Tengo un programa simple de C. Digamos, por ejemplo, que tengo una matriz int y char de longitud 20. Necesito 24 bytes en total.

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

La pila debe estar alineada con un límite de 16 bytes, por lo que supongo que un compilador reservará 32 bytes. Pero cuando compilo dicho programa con gcc x86-64 y leo el ensamblaje de salida, el compilador reserva 64 bytes.

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

Me da

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

¿Porqué es eso? Cuando programo el ensamblaje, siempre reservo solo la memoria mínima que necesito sin ningún problema. ¿Es eso una limitación del compilador que tiene problemas para evaluar la memoria necesaria o hay alguna razón para ello?

Aquí está 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) 

De hecho, los compiladores pueden reservar memoria adicional para ellos.

Gcc tiene una bandera, -mpreferred-stack-boundary , para establecer la alineación que mantendrá. De acuerdo con la documentación , el valor predeterminado es 4, que debería producir una alineación de 16 bytes, necesaria para las instrucciones SSE.

Como VermillionAzure señaló en un comentario , debe proporcionar su versión de gcc y las opciones de tiempo de compilación (use gcc -v para mostrarlas).





allocation