Unix/Linux编程:在堆栈上分配内存------alloca()

221 篇文章 42 订阅

和 malloc 函数包中的函数功能一样,alloca()也可以动态分配内存,不过不是从堆上分配内存,而是通过增加栈帧的大小从堆栈上分配。根据定义,当前调用函数的栈帧位于堆栈的顶部,故而这种方法是可行的。因此,帧的上方存在扩展空间,只需修改堆栈指针值即可

NAME
       alloca - allocate memory that is automatically freed

SYNOPSIS
       #include <alloca.h>

       void *alloca(size_t size);

参数 size 指定在堆栈上分配的字节数。函数 alloca()将指向已分配内存块的指针作为其返回值。 不需要(实际上也绝不能)调用 free()来释放由 alloca()分配的内存。同样,也不可能调用 realloc()来调整由 alloca()分配的内存大小。

旧版本的 glibc 和其他一些 UNIX 实现(主要是 BSD 的衍生版本),要获取 alloca()声明 需引入<stdlib.h>而非<alloca.h>

若调用alloca()造成堆栈溢出,则程序的行为无法预知,特别是在没有收到一个NULL 返回值通 知错误的情况下。(事实上,在此情况下,可能会收到一个SIGSEGV 信号)

请注意,不能在一个函数的参数列表中调用 alloca(),如下所示

func(x, alloca(size), z)  // error!!!

这会使alloca()分配的堆栈空间出现在当前函数参数的空间内(函数参数都位于栈帧内的固定位置)。正确的写法:

void * y;

y = alloca(size);

func(x, y, z);

使用 alloca()来分配内存相对于 malloc()有一定优势。

  • 其中之一是,alloca()分配内存的速 度要快于 malloc(),因为编译器将 alloca()作为内联代码处理,并通过直接调整堆栈指针来实 现。
  • 此外,alloca()也不需要维护空闲内存块列表。
  • 另一个优点在于,由 alloca()分配的内存随栈帧的移除而自动释放,亦即当调用 alloca 的 函数返回之时。之所以如此,是因为函数返回时所执行的代码会重置栈指针寄存器,使其指 向前一帧的末尾(即,假设堆栈向下增长,则指向恰好位于当前栈帧起始处之上的地址)。由 于在函数的所有返回路径中都无需确保去释放所有的已分配内存,一些函数的编码也变得简 单得多

在信号处理程序中调用 longjmp()(6.8 节)或 siglongjmp()(21.2.1 节)以执行非局部跳 转时,alloca()的作用尤其突出。此时,在“起跳”函数和“落地”函数之间的函数中,如果 使用了 malloc()来分配内存,要想避免内存泄漏就极其困难,甚至是不可能的。与之相反, alloca()完全可以避免这一问题,因为堆栈是由这些调用展开的,所以已分配的内存会被自动释放

 

 

不提倡使用

-   C99 支持变长数组(VLA), 它可以用来更好的 完成 alloca() 以前的任务

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值