12

我想了解堆栈区域上的运行时内存分配以及它与堆区域上的运行时内存分配有何不同。

我知道如何使用库函数分配内存。

#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 相关联,以及它们在两者中的工作方式。

4

3 回答 3

13

简而言之,它们通常不使用系统调用,除非可用内存不足。

两者的行为不同,所以我解释不同。

malloc

假设最初您的程序有 1MB(例如)可供分配的可用内存。malloc是一个(标准)库函数,它占用这 1MB,查看您要分配的内存,将 1MB 的一部分切出并给您。为了记账,它保存了一个未分配内存的链表。然后,该free函数将被释放的块添加回空闲列表,从而有效地释放内存(即使操作系统仍然没有取回任何内存,除非free确定您有太多内存并实际上将其归还给操作系统)。

只有当您用完 1MB 时,才会malloc真正向操作系统请求更多内存。系统调用本身是平台相关的。例如,您可以看一下这个答案

阿洛卡

这不是一个标准函数,它可以通过多种方式实现,其中任何一种都可能不会调用任何系统函数(除非它们足够好来增加你的堆栈大小,但你永远不知道)。

(或等效地(C99)标准可变长度数组(VLA)所做的)是alloca通过调整适当的寄存器(例如esp在 x86 中)来增加当前函数的堆栈帧。任何碰巧在同一个堆栈帧上但位于可变长度数组(或allocaed 内存)之后的变量将被寻址,ebp + size_of_vla + constant而不是旧的 simple ebp + constant

由于堆栈指针在函数返回时(或通常在任何块退出时)恢复到前一个函数的帧,因此{}任何堆栈内存allocated 将被自动释放。

于 2013-03-26T14:57:05.200 回答
3

alloca()函数通常由编译器供应商实现,根本不必是“系统调用”。

由于它所要做的就是在本地堆栈帧上分配空间,因此它可以非常简单地实现,因此与malloc().

它的Linux手册页说:

内联代码通常由一条调整堆栈指针的指令组成,并且不检查堆栈溢出。

另外,我不确定您是否意识到当调用alloca()exits的函数时内存会“自动”释放。这很重要,你不能alloca()用来做长期分配。

于 2013-03-26T14:50:08.533 回答
0

alloca根据其手册页,该函数是一个内联函数,将由编译器特殊处理并扩展(至少对于gcc)。
该行为是实现定义的,因此不应使用,因为您不能保证它始终以相同的方式工作。

于 2013-03-26T14:48:51.440 回答