Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/157.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何优化c++;编译器是否重用函数的堆栈槽? 如何优化C++编译器决定函数的栈时隙(函数栈的一部分)何时不再需要该函数,从而可以重用它的内存?br> 所谓堆栈槽,我指的是函数堆栈框架的一部分,不一定是函数的整个堆栈框架。澄清问题的一个例子是,假设我们有一个函数,在它的作用域中定义了六个整数变量,当在函数中使用第六个变量时,第五个变量变得无用,所以编译器可以对第五个和第六个变量使用相同的内存块。 关于这个主题的任何信息都值得欣赏。_C++_Optimization_Memory_Compiler Construction_Stack - Fatal编程技术网

如何优化c++;编译器是否重用函数的堆栈槽? 如何优化C++编译器决定函数的栈时隙(函数栈的一部分)何时不再需要该函数,从而可以重用它的内存?br> 所谓堆栈槽,我指的是函数堆栈框架的一部分,不一定是函数的整个堆栈框架。澄清问题的一个例子是,假设我们有一个函数,在它的作用域中定义了六个整数变量,当在函数中使用第六个变量时,第五个变量变得无用,所以编译器可以对第五个和第六个变量使用相同的内存块。 关于这个主题的任何信息都值得欣赏。

如何优化c++;编译器是否重用函数的堆栈槽? 如何优化C++编译器决定函数的栈时隙(函数栈的一部分)何时不再需要该函数,从而可以重用它的内存?br> 所谓堆栈槽,我指的是函数堆栈框架的一部分,不一定是函数的整个堆栈框架。澄清问题的一个例子是,假设我们有一个函数,在它的作用域中定义了六个整数变量,当在函数中使用第六个变量时,第五个变量变得无用,所以编译器可以对第五个和第六个变量使用相同的内存块。 关于这个主题的任何信息都值得欣赏。,c++,optimization,memory,compiler-construction,stack,C++,Optimization,Memory,Compiler Construction,Stack,简单的部分是:当函数退出时,该函数的所有局部变量都被释放。因此,函数exit表示可以释放整个堆栈帧。不过,这是一个不需要动脑筋的问题,如果你是在追求“优化编译器”,你就不会提到它了 理论上,编译器可以对函数进行流分析,找出在什么时候使用了哪些内存块,甚至可以根据变量可用的顺序重新排序堆栈分配。然后,如果新的自动变量被引入函数的中间或函数内嵌套的其他范围内(而不是在其开始),则可以重新使用最近释放的时隙。 在实践中,这听起来像是在旋转齿轮,我怀疑只要变量进入作用域并在作用域结束时通过减少堆栈指针从

简单的部分是:当函数退出时,该函数的所有局部变量都被释放。因此,函数exit表示可以释放整个堆栈帧。不过,这是一个不需要动脑筋的问题,如果你是在追求“优化编译器”,你就不会提到它了

理论上,编译器可以对函数进行流分析,找出在什么时候使用了哪些内存块,甚至可以根据变量可用的顺序重新排序堆栈分配。然后,如果新的自动变量被引入函数的中间或函数内嵌套的其他范围内(而不是在其开始),则可以重新使用最近释放的时隙。


在实践中,这听起来像是在旋转齿轮,我怀疑只要变量进入作用域并在作用域结束时通过减少堆栈指针从块中弹出,堆栈就会被简单地分配。但我承认我不是这方面的专家。具有更权威知识的人可能会来纠正我。

编辑:我将这个问题解释为“编译器如何重用堆栈中的特定内存字?”以下大部分回答了这个问题,结尾的注释回答了这个问题,“编译器如何重用函数所需的所有堆栈空间?”

大多数编译器不会首先分配堆栈插槽。相反,对于每个函数体,它们所做的是将对变量的每次更新以及能够看到特定赋值的对该变量的所有访问视为所谓的变量生存期。一个被多次赋值的变量将导致编译器创建多个生存期

(当多个分配可以通过不同的控制路径到达一个访问时,这种想法会出现一些复杂的情况;这可以通过对这种想法的巧妙增强来解决,我在这里不讨论)

在代码中的任何一点上,都有一组有效的变量生存期;当您选择不同的代码点时,您有不同的有效变量生存期。编译器的实际问题是为每个生命周期分配不同的寄存器或堆栈插槽。我们可以把这看作是一个图着色问题:每个生命周期都是一个节点,如果两个生命周期可以在代码中的某个点重叠,那么从该节点到表示另一个生命周期的另一个节点就有一个“干涉”弧。可以为图形着色(或等效地使用数字而不是颜色),以便由干涉弧连接的两个节点没有相同的颜色(数字);您可能需要使用任意大的数字来执行此操作,但对于大多数函数,数字不必非常大。如果您这样做,颜色(数字)将告诉您一个安全堆栈槽,用于特定变量生存期的指定值。(这个想法通常分为两个阶段:一个是分配寄存器,另一个是为不适合寄存器的生命周期分配堆栈插槽)

通过确定图形上用作颜色的最大数字,编译器知道在最坏的情况下需要多少插槽,并且可以在函数进入时保留那么多存储空间

有很多复杂之处:不同的价值观占用不同的空间,等等,但基本思想就在这里。并非所有的编译器都使用图形着色技术,但几乎所有的编译器都知道如何以避免隐含干扰的方式分配堆栈插槽和寄存器。因此,他们知道堆栈插槽编号和堆栈帧的大小


编辑。。。键入时,问题似乎被解释为“函数的堆栈帧何时消失”?答案是,在函数退出时。编译器已经知道它有多大了。在函数执行过程中无需推送或弹出堆栈;它知道根据图着色确定的堆栈槽编号将所有内容放在何处。

如果我正确理解了这个问题,这是关于调用链接的,即从函数调用函数而不分配新的堆栈帧

当调用可以转换为尾部调用时,这是可能的,尾部调用是返回前的最后一次操作。这样,所有局部变量(堆栈)都已超出范围,因此可以重用空间。然后,编译器生成一个
跳转
,而不是
调用
指令。原始返回地址仍然位于堆栈上的正确位置


我可能在这里忽略了很多细节,但这就是我的想法。

堆栈槽是什么意思?你必须解释一下“函数的堆栈槽”是什么意思。我猜“堆栈槽”是指“堆栈框架”。是吗?使用_alloca()或在您的CRT上调用的任何东西使其更有趣。“堆栈槽”并没有那么含糊不清。这是简化的RISC-y堆栈视图的一部分。基本上,简化是可以推送到堆栈上的所有数据都是相同大小的——指针、整数或浮点。假设它是4个字节。然后,一个12字节的堆栈帧将包含3个堆栈槽,即能够容纳三个变量。答案没有错,只是您没有说明何时保留堆栈空间。当然,这取决于编译器,但通常没有理由不重新选择