C 堆栈上的运行时内存分配
我想知道堆栈区域上的运行时内存分配,以及它与堆区域上的运行时内存分配有何不同 我知道如何使用库函数分配内存C 堆栈上的运行时内存分配,c,C,我想知道堆栈区域上的运行时内存分配,以及它与堆区域上的运行时内存分配有何不同 我知道如何使用库函数分配内存 #include<alloca.h> void *alloca(size_t size); //(for runtime memory on stack) #include<stdlib.h> void *malloc(size_t size); //(for run time memory on heap) #包括void*alloca(大小)//(用于堆栈上
#include<alloca.h> void *alloca(size_t size); //(for runtime memory on stack)
#include<stdlib.h> void *malloc(size_t size); //(for run time memory on heap)
#包括void*alloca(大小)//(用于堆栈上的运行时内存)
#包括void*malloc(大小)//(用于堆上的运行时内存)
我还知道,如果我们使用alloca函数,我们不需要显式地释放内存,因为它与堆栈关联,它会自动释放
我想知道哪些系统调用与alloc和malloc相关,以及它们在两者中的工作方式。根据它的定义,
alloca
函数是一个内联函数,将由编译器专门处理和扩展(至少对于gcc
)。行为是由实现定义的,因此不应使用,因为您无法保证它始终以相同的方式工作。函数
alloca()
通常由编译器供应商实现,不必是“系统调用”
由于它只需在本地堆栈帧上分配空间,因此实现起来非常简单,因此与malloc()
相比,速度非常快
报告说:
内联代码通常由调整堆栈指针的单个指令组成,并且不检查堆栈溢出
另外,我不确定您是否意识到,当调用
alloca()
的函数退出时,内存会“自动”释放。这一点非常重要,您不能使用alloca()
进行长期分配。简而言之,除非可用内存不足,否则它们通常不使用系统调用
两者的巴哈维奥语都不同,所以我的解释不同
马洛克
假设最初您的程序有1MB(例如)的可用内存可供分配malloc
是一个(标准)库函数,它占用1MB的内存,查看要分配的内存,从1MB中剪切出一部分并将其提供给您。对于簿记,它保留一个未分配内存的链接列表。然后,free
函数将被释放的块添加回空闲列表,从而有效地释放内存(即使操作系统仍然没有收回任何内存,除非free
确定您的内存太多,并实际将其返回给操作系统)
只有当1MB内存用完时,malloc
才会请求操作系统提供更多内存。系统调用本身取决于平台。例如,您可以看一看
阿洛卡
这不是一个标准函数,可以用各种方式实现,其中没有一种可能调用任何系统函数(除非它们足够好,可以增加堆栈大小,但您永远不知道)
alloca
所做的(或相当于(C99)标准可变长度数组(VLA)所做的)是通过调整适当的寄存器(例如x86中的esp
)来增加当前函数的堆栈帧。任何恰好位于同一堆栈帧上但位于可变长度数组(或alloca
ed内存)之后的变量将由ebp+size\u of_vla+constant
而不是旧的简单ebp+constant
进行寻址
由于堆栈指针在函数返回时(或通常在任何
{}
块退出时)恢复到上一个函数的帧,因此任何堆栈内存alloca
ted都将自动释放。您所说的是什么意思?您是否在问alloc()
和malloc()
的内部结构如何工作?alloca
是非标准的,malloc
的实现将非常依赖于机器和编译器。你能提供一些你想知道的细节吗?为什么知道哪个系统调用使用alloca是很重要的?另外,alloca
已被弃用,建议避免使用它。系统调用什么brk()
和sbrk()
?alloca
没有被弃用,因为它从来都不是标准的一部分。它在GNU软件中得到了很好的支持(并且大量使用)——他们建议使用它。不过,这取决于实现,在其他平台上,它可能有缺陷,甚至不存在。我认为说不应该使用实现扩展有点苛刻——只要您知道它可能会限制可移植性就可以了。@teppic同意,但据我所知,应该避免它