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同意,但据我所知,应该避免它