将工作分成5个函数,而不是一个大函数,在C中是不是更有内存效率,因为在给定的时间,内存中的变量更少,因为堆栈帧被释放的频率更高?它依赖于编译器和优化吗?如果是这样的话,在哪些编译器中更快呢?
答案是,有很多局部变量,堆栈框架来自一个集中的main,而不是在彼此的顶部创建。
我知道将函数分解为更小的函数的其他优点。请回答此问题,仅限于内存使用情况。
发布于 2011-08-11 17:35:06
它可能会减少你的程序的堆栈使用的“高水位线”,如果是这样的话,可能会减少程序的总体内存需求。
是的,这取决于优化。如果优化器内联函数调用,您很可能会发现所有内联函数的所有变量都被包装到一个大堆栈帧中。任何值得使用的编译器都能够内联*,所以这种情况的发生并不依赖于编译器。具体何时发生,将有所不同。
但是,如果您的局部变量很小,那么您的程序很少会使用比启动时自动分配的堆栈更多的堆栈。除非您超出了最初给出的值,否则您使用的量对总体内存需求没有任何影响。
如果你把很大的结构放在堆栈上(几千字节),或者如果你在一台千字节是很多内存的机器上,那么它可能会对整体内存使用量产生影响。因此,如果你所说的“许多局部变量”是指几十个int和指针,那么不,你所做的任何事情都不会有任何显著的区别。如果你所说的“许多局部变量”指的是几十个10k的缓冲区,或者如果你的函数递归非常深,以至于你的几十个int有几百个级别,那么它至少可能会有所不同,这取决于操作系统和配置。
堆栈和堆通过通用RAM彼此增长,中间的空闲内存可以被它们中的任何一个平等使用的模型已经过时了。除了极少数非常受限制的系统外,内存模型不再以这种方式设计。在现代的OSes中,我们有所谓的“虚拟内存”,堆栈空间是一次一个页面地分配给你的程序。它们中的大多数会在使用时自动分配更多的堆栈页面,直到配置的限制通常非常大。有几个不能自动扩展堆栈(Symbian上一次我使用它是几年前的事了,虽然可以说Symbian不是一个“现代”操作系统)。如果您使用的是嵌入式操作系统,请查看手册中关于堆栈的说明。
无论哪种方式,影响总内存使用的唯一因素就是一次需要多少页的堆栈。如果你的系统自动扩展栈,你甚至不会注意到你使用了多少。如果没有,您将需要确保为程序提供足够的堆栈,以满足其高水位标记,这时您可能会注意到堆栈的过度使用。
简而言之,这是理论上有意义的事情之一,但在实践中,这种差异几乎总是微不足道的。只有当您的程序相对于其运行环境的资源使用大量堆栈时,它才有意义。
*使用C编译器编写图片或其他东西的人,基本上是一个非优化的汇编程序,我称他们的编译器“不值得使用”,这让他们感到不快。这类设备上的堆栈与“典型”系统是如此不同,以至于答案无论如何都是不同的。
发布于 2011-08-11 14:00:35
我认为在大多数情况下,分配给堆栈的内存区域(对于整个程序)保持不变。使用量将根据调用堆栈的深度而变化,当使用较少的变量时,使用量会更少(但请注意,函数调用也会推送返回地址和堆栈指针)。
此外,它还取决于函数的调用方式。例如,如果连续调用两个函数,并且第一个函数的堆栈在调用第二个函数之前弹出,那么如果第一个函数调用第二个函数,那么您将使用较少的stack..but,然后返回到使用一个大函数时的位置(加上函数调用开销)。
发布于 2011-08-11 14:15:05
是的,同样的道理,在喷气式飞机上使用更好的涂料可以提高其空气动力学性能。好吧,这是一个糟糕的类比,但重点是,如果有任何问题,让事情变得清晰和电报或试图使用更多的功能,去电报。在大多数情况下,这些都不是相互排斥的,因为初学者往往会给出太多的子例程或函数来完成。
在内存方面,我认为如果你真的拆分工作(f,然后g,然后h),那么你会看到一些分钟的可用内存增加,但如果这些是相互依赖的,那么你就不会看到。
正如@Joel Burget所说,内存管理并不是代码结构化的真正考虑因素。
这只是我的观点。
https://stackoverflow.com/questions/7021422
复制相似问题