我想了解堆栈区域的运行时内存分配以及它与堆区域上的运行时内存分配的不同之处。
我知道如何使用库函数分配内存。
#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)
我也知道如果我们使用alloca函数,我们不需要显式释放该内存,因为它与堆栈相关联,它会自动释放。
我想知道哪些系统调用与alloc和malloc相关联,以及它们如何在两者中工作。
答案 0 :(得分:12)
简而言之,除非耗尽可用内存,否则他们通常不会使用系统调用。
这两种行为都不同,所以我的解释不同。
假设您的程序最初有1MB(例如)可用内存用于分配。 malloc
是一个(标准)库函数,占用1MB,查看要分配的内存,将1MB的一部分删除并提供给您。对于簿记,它保留了未分配记忆的链接列表。 free
函数然后将释放的块添加回空闲列表,有效地释放内存(即使操作系统仍然没有获得任何内存,除非{{1}判断你有太多的内存,并实际上把它还给了操作系统。)
只有当你的1MB用完时,free
才会向操作系统询问更多内存。系统调用本身与平台有关。例如,您可以查看this answer。
这不是一个标准函数,它可以以各种方式实现,其中任何一个都可能调用任何系统函数(除非它们足够好以增加堆栈大小,但你永远不知道)。
malloc
做什么(或等效于(C99)标准可变长度数组(VLA))是通过调整适当的寄存器来增加当前函数的堆栈帧(例如x86中的alloca
)。任何恰好位于同一堆栈帧但位于可变长度数组(或esp
ed内存之后)的变量将由alloca
而不是旧的简单ebp + size_of_vla + constant
来处理。
由于在函数返回时(或通常在任何ebp + constant
块的退出时)堆栈指针被恢复到前一个函数的帧,因此任何堆栈内存{}
都会自动释放。
答案 1 :(得分:3)
alloca()
函数通常由编译器供应商实现,根本不必是“系统调用”。
由于它只需要在本地堆栈帧上分配空间,因此可以简单地实现 very ,因此与malloc()
相比,速度非常快。
内联代码通常由调整堆栈指针的单个指令组成,并且不检查堆栈溢出。
此外,当调用alloca()
的函数退出时,我不确定您是否“自动”释放内存。这非常重要,您不能使用alloca()
进行长期分配。
答案 2 :(得分:0)
alloca
函数根据其manpage函数内联,并由编译器专门处理并扩展(至少gcc
)。
行为是实现定义的,因此不应该使用,因为你无法保证它始终以相同的方式工作。