gcc如何确定基于C的函数将使用的堆栈大小? [英] How does the gcc determine stack size the function based on C will use?

查看:1200
本文介绍了gcc如何确定基于C的函数将使用的堆栈大小?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我用C编程语言编写程序,并使用objdump将可执行文件转换为asm文件。我不知道gcc如何确定函数将使用的堆栈大小?

  int a()
{
int temp [1024 * 1024];
temp [0] = 1;
return temp [0];
}

这只是为了解释问题,忽略它是天真的。 gcc是否会为函数a分配真正的1024 * 1024字节空间?



如果函数有点复杂,有时会有很多局部变量,编译器如何确定堆栈大小?

解决方案

首先,至少没有优化,GCC会发出分配1024 * 1024 int -s(不是字节;通常是 int 是4字节,因为 sizeof(int)== 4 )在调用堆栈(即4M字节!)。这可能太多了,并且您可能会收到分段错误,因为堆栈溢出。另见 setrlimit(2) execve(2)系统调用。



某些版本的GCC可以优化您的代码。在Linux / Debian / Sid / x86-64上, gcc-4.8 -O3 -fverbose-asm -S stonestrong.c 命令(实际上使用GCC 4.8.2)能够优化您的代码:

  .globl a 
.type a,@function
a:
.LFB0:
.cfi_startproc
movl $ 1,%eax#,
ret
.cfi_endproc
.LFE0:
.size a,。-a

因此,在您的特定情况下,使用 -O3



编译器使用相当复杂的优化算法确定堆栈大小和布局。每个函数通常都有自己的堆栈框架。当编译器进行优化时,调用帧的给定槽可能用于多个源代码变量,并且给定源变量可能不需要任何栈槽(因为它可以保存在寄存器中),或者可以使用其中的几个(一个块用于一个块,另一个用于另一个块等)。



您可能想要探索GCC使用的各种内部表示(特别是Gimple) -fdump-tree-all (它会转储数百个文件!)到 gcc 命令。您可能希望使用 MELT 扩展GCC(通过添加新的通行证)或检查内部表示。



有些变量或某些中间值甚至没有保存在堆栈中,而只保存在寄存器中。编译器在注册分配上努力(优化时)(这是一个有其自己的难题专家)。另请参阅



一般规则在C(或C ++)中编写代码时要避免使用过大的调用帧;通常情况下,您希望本地变量的最多消耗不超过几千字节。

程序优化可能非常困难;但是目前的编译器相当擅长如上所述的优化。使用GCC,您需要明确地启用优化(例如 -O2 -O3 和其他许多标志)。 GCC有超过一千万行源代码,其中一半是中端优化(不依赖于源语言或目标处理器)。

I write program in C programming language, and I use objdump to translate the executable file to asm file. I have no idea how gcc determine the stack size the function will use?

    int a()
    {
         int temp[1024 * 1024];
         temp[0] = 1;
         return temp[0];
    }

It's just for problem explanation, ignore that it's naïve. Will the gcc allocate really 1024 * 1024 bytes space for function a?

If the function is a little complicated, sometimes a lot of local variables, how does the compiler determine the stack size?

解决方案

First, at least without optimizations, GCC will emit code that allocates 1024*1024 int-s (not bytes; often an int is 4 bytes because sizeof(int)==4) on the call stack (i.e. 4Mbytes!). This might be too much, and you might get a segmentation fault because of the stack overflow. See also the setrlimit(2) and execve(2) syscalls.

Some versions of GCC are able to optimize your code. On Linux/Debian/Sid/x86-64 the gcc-4.8 -O3 -fverbose-asm -S stonestrong.c command (actually using GCC 4.8.2) is able to optimize your code to:

    .globl  a
    .type   a, @function
a:
.LFB0:
    .cfi_startproc
    movl    $1, %eax    #,
    ret
    .cfi_endproc
.LFE0:
.size   a, .-a

So in your particular case, no stack frame at all is needed when optimizing with -O3.

The compiler determines the stack size and layout using quite complex optimization algorithms. Each function usually has its own stack frame. When the compiler is optimizing, a given slot of the call frame might be used for several source code variables, and a given source variable might not need any stack slot (because it could be kept in a register), or maybe use several of them (one slot for a block, another for another, etc...).

You may want to explore the various internal representations (notably Gimple) used by GCC by passing -fdump-tree-all (which will dump hundreds of files!) to your gcc command. You may want to use MELT to extend GCC (by adding your new passes) or inspect the internal representations.

Some variables or some intermediate values are not even kept on the stack, but only in register. The compiler works hard (when optimizing) on register allocation (which is a difficult question having its own experts). See also this.

A general rule of thumb when coding in C (or in C++) is to avoid too large call frames; often, you want your local variables to consume no more than a few kilobytes at most.

Program optimization can be very hard; however current compilers are quite good at optimization like the one above. With GCC you need to enable optimizations (e.g. with -O2 or -O3 and many other flags) explicitly. GCC has more than ten millions lines of source code, and half of them are middle-end optimizations (not depending on the source language or the target processor).

这篇关于gcc如何确定基于C的函数将使用的堆栈大小?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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