简体   繁体   English

gcc如何确定基于C的函数将使用的堆栈大小?

[英]How does the gcc determine stack size the function based on C will use?

I write program in C programming language, and I use objdump to translate the executable file to asm file. 我用C编程语言编写程序,并使用objdump将可执行文件转换为asm文件。 I have no idea how gcc determine the stack size the function will use? 我不知道gcc如何确定函数将使用的堆栈大小?

    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? gcc是否会为函数a分配1024 * 1024字节的空间?

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 (ie 4Mbytes!). 首先,至少在没有优化的情况下,GCC将发出代码,在调用堆栈上分配1024 * 1024个int (不是字节;通常int是4个字节,因为sizeof(int)==4 )(即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. 另请参见setrlimit(2)execve(2)系统调用。

Some versions of GCC are able to optimize your code. 某些版本的GCC能够优化您的代码。 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: 在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

So in your particular case, no stack frame at all is needed when optimizing with -O3 . 因此,在您的特定情况下,使用-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. 您可能希望通过将-fdump-tree-all (将数百个文件转储!)传递给您的gcc命令来探索GCC使用的各种内部表示(特别是-fdump-tree-all )。 You may want to use MELT to extend GCC (by adding your new passes) or inspect the internal representations. 您可能希望使用MELT扩展GCC(通过添加新的通行证)或检查内部表示。

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 ; 用C(或C ++)编码时的一般经验法则是避免使用过大的调用帧 ; 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 (eg with -O2 or -O3 and many other flags) explicitly. 使用GCC,您需要明确启用优化(例如,使用-O2-O3和许多其他标志)。 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拥有超过一千万行源代码,其中一半是中端优化(不依赖于源语言或目标处理器)。

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

It does so by looking at the size of the variables used and adding them. 它通过查看所用变量的大小并添加它们来实现。 (As a first approximation, anyway. For performance and correctness reasons, alignment and padding and whatever else might be added to the allocated amount as well.) (作为第一个近似值,无论如何。出于性能和正确性的原因,对齐和填充以及可能添加到分配量中的任何其他内容。)

Will the gcc allocate really 1024 * 1024 bytes space for function a? gcc是否会为函数a分配1024 * 1024字节的空间?

If you tell it to do so (you disable optimizations), it most probably will. 如果你告诉它这样做(你禁用优化),它很可能会。 (Not 1024 * 1024 bytes, though -- rather 1024 * 1024 * sizeof(int) bytes. At least.) But you can just go ahead and compile it and look at the generated assembly. (不是1024 * 1024字节,而是1024 * 1024 * sizeof(int)字节。至少。)但是你可以继续编译它并查看生成的程序集。

But your function is quite a simple one, and its behavior is trivial to reason about, so I'd expect any decent compiler to optimize away the array declaration. 但是你的函数非常简单,它的行为很容易理解,所以我希望任何像样的编译器都能优化数组声明。 (But again, look at what actual assembly it outputs. It might vary from version to version, with flags, with platforms, etc.) (但是,请再看一下它输出的实际装配。它可能因版本而异,有标志,有平台等)

If the function is a little complicate, sometimes a lot of local variables, how does the compiler determine the stack size? 如果函数有点复杂,有时会有很多局部变量,编译器如何确定堆栈大小?

The complexity of your function does not matter. 功能的复杂性无关紧要。 If it's too complicated, then maybe the compiler can do less optimizations. 如果它太复杂,那么编译器可能会做较少的优化。 But it definitely can compute the upper bound of the necessary memory by - naively - adding all the sizes of the variables used. 但它绝对可以通过 - 添加所有变量的大小来计算必要内存的上限。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM