在C语言中,使用局部变量分配/释放内存和直接分配/释放内存哪个更好?为什么?

3
如果我需要进行字符串操作或操纵任何类型的数组,无论是标准类型如int还是自定义数据结构。使用本地变量还是动态分配和释放内存哪种更好呢?
我知道如果你使用本地变量,则不需要分配/释放内存,这可能会使我们免受内存泄漏的影响。但我想知道为什么人们喜欢使用动态分配内存。它只是一种编码风格还是真的有其好处。同时,它是否取决于我们正在编译的系统,还是取决于编译器?
即使系统具有足够的内存和速度资源,哪种技术更适合优化代码?
5个回答

3
本地的,基于栈的操作通常在速度方面胜过动态内存分配。原因是,在动态内存分配期间,程序需要向操作系统请求帮助。这会导致上下文切换(非常缓慢/昂贵),并阻塞,直到操作系统返回一块内存(甚至可能无法返回)。
然而,您的程序已经有了自己的堆栈,因此可以根据需要进行操作,而不会中断执行流程(除了多任务处理,这是您无法控制的)。
动态内存分配的好处是,有时候我们不知道需要分配多少内存直到运行时才能确定。如果没有动态分配,我们就需要预先分配一个静态缓冲区,并为最坏情况保留足够的内存(这可能超出我们的资源范围)。

2

在这个问题上,你应该问的是:我知道程序在运行时需要多少内存吗?

如果你知道只需要3个int变量,那么你应该使用局部变量。没有内存泄漏,除非有足够的内存可用,否则你的程序将无法运行。

如果你无法预测需要多少内存,比如说你需要将文件读入内存,那么你别无选择,只能使用动态分配。


2
有两种选择都有很好的理由。
通常,当以下情况时,您会使用堆分配(例如malloc):
  • 直到执行时才知道需要多大的内存分配
  • 当它占用大量堆栈内存(或全部)时
  • 当分配需要超出当前作用域时(例如从函数返回)

这也取决于我们正在编译的系统还是取决于编译器吗?

这取决于您要针对的编译器和系统。

即使系统具有足够的内存和速度资源,哪种技术更适合优化代码?

在大多数情况下,更重要的是如何使用和访问内存和硬件。对于优化,局部变量具有更多的优势。然而,在某些情况下,编译器可能会优化掉对malloc的调用。

但愿我的编译器永远不会杀死我的malloc调用并将它们替换为其他东西。你能给我举个这种情况的例子吗? - Michael Dorgan
@MichaelDorgan int* const a = malloc(sizeof(int)); \n free(a); 是最简单的情况。请注意,此分配大小已知,并且内存在本地释放。当然,有些情况下您可以读写该内存,并且该引用不会离开作用域,或者编译器或其他优化器(例如LTO或中间字节码表示)可以证明该内存永远不会共享,其中堆栈可能会被使用而不是malloc(或其他分配器)。 - justin

0

本地非动态内存分配的调用通常会更快,因为它们只需要堆栈操作而不需要堆管理,并且具有有限的作用域。但是,它们的作用域有限,通常需要让内存持续到函数之外。

在一些嵌入式系统中,由于堆栈空间有限,即使在本地变量上也会调用malloc以获取更大的堆,但通常情况下,您希望将内存访问限制在其预期的范围内-无论性能考虑如何。


真的吗?在大多数情况下,嵌入式系统会避免使用malloc,因为它非常慢。他们更倾向于使用静态变量和内存池。 - milleniumbug
取决于情况。我见过两种做法——全局/静态变量需要在预启动时初始化,而malloc可以等到所有东西都就位后再进行分配,就像堆栈分配一样。 - Michael Dorgan
对我来说,限制堆栈空间那么多仍然没有意义,因为堆存在(也就是说,为了拥有堆结构而产生记忆体开销)。 - milleniumbug
免责声明:我绝对不是一个嵌入式系统专家,只是在这里告诉大家,当Stack Overflow用户们谈论嵌入式系统时,他们说他们不使用malloc。所以我很好奇你的答案是相反的。我的意思是,在系统中使用malloc需要有一个链接列表、块和智能内存管理,这在时间和空间上都比将静态变量设为0并移动堆栈指针更复杂。 - milleniumbug
是的,malloc 比栈慢一些,内存效率也稍低。但是,你几乎总会有某种形式的 malloc 系统设置,如链表和动态数组等需要它。每个单独的 malloc 都会消耗一些跟踪器/链接字节和可能的内部碎片。但是,它还允许你在运行时调用初始化代码(或构造函数),而不是在启动时当硬件可能没有完全设置好时调用。对于单个大的分配和释放,我宁愿调用一次 malloc,而不是让静态内存闲置,供其他人使用,并支付一些字节的税。 - Michael Dorgan
显示剩余2条评论

0
作为默认位置,除非您需要分配超出创建它的范围或分配很大,否则首选堆栈分配。在您的情况下,您正在询问一个本地变量,应该在封闭范围结束时被释放。一个经验法则是,如果分配少于 1K ,则使用堆栈适当,否则使用堆。 Microsoft的_malloca使用此阈值在堆栈和堆分配之间进行切换。当然,这取决于您希望分配的栈处于什么状态。例如,在深度递归函数中进行1K堆栈分配可能不明智。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接