【原创】浅谈指针(十一)alloca函数

前言 好几天没写了,最近网课,事情也比较多,今天多写点东西。

目录

  • 前言
  • alloca函数
    • 1.简介
    • 2.反汇编看alloca
    • 3.手工调用alloca函数
    • 4.注意事项

alloca函数 1.简介 之前看《30天自制操作系统》的时候,看见了这样一个东西:
【原创】浅谈指针(十一)alloca函数
文章图片

没错,这就是alloca函数。
2.反汇编看alloca 现在,我们把VS打开,看看反汇编是如何的:
(顺便说一下反汇编的方法,就是下两个断点,如图)
【原创】浅谈指针(十一)alloca函数
文章图片

然后左上角就会出现反汇编的页面,点进去
【原创】浅谈指针(十一)alloca函数
文章图片

代码如下:
#include "stdafx.h" #include #include #define N 100 int main(){ char a[N]; for(int i=1; i<=N; i++){ a[i]=0; } }

【【原创】浅谈指针(十一)alloca函数】反汇编的结果是:
pushebp 004D1381 8B ECmovebp,esp 004D1383 81 EC 3C 01 00 00subesp,13Ch 004D1389 53pushebx 004D138A 56pushesi 004D138B 57pushedi 004D138C 8D BD C4 FE FF FFleaedi,[ebp-13Ch] 004D1392 B9 4F 00 00 00movecx,4Fh 004D1397 B8 CC CC CC CCmoveax,0CCCCCCCCh 004D139C F3 ABrep stosdword ptr es:[edi] 004D139E A1 00 70 4D 00moveax,dword ptr [___security_cookie (4D7000h)] 004D13A3 33 C5xoreax,ebp 004D13A5 89 45 FCmovdword ptr [ebp-4],eax

似乎看不出什么名堂来,但是如果一旦我们把N改为更大的数字,例如100000,再来看看:
00FF1380 55pushebp 00FF1381 8B ECmovebp,esp 00FF1383 B8 78 87 01 00moveax,18778h 00FF1388 E8 30 FE FF FFcall@ILT+440(__alloca_probe) (0FF11BDh) 00FF138D 53pushebx 00FF138E 56pushesi 00FF138F 57pushedi 00FF1390 8D BD 88 78 FE FFleaedi,[ebp-18778h] 00FF1396 B9 DE 61 00 00movecx,61DEh 00FF139B B8 CC CC CC CCmoveax,0CCCCCCCCh 00FF13A0 F3 ABrep stosdword ptr es:[edi] 00FF13A2 A1 00 70 FF 00moveax,dword ptr [___security_cookie (0FF7000h)] 00FF13A7 33 C5xoreax,ebp 00FF13A9 89 45 FCmovdword ptr [ebp-4],eax

看第四行,有一个叫做 call @ILT+440(__alloca_probe)的一个东西,
汇编语言中,call指令后面跟的东西是一个函数,那么alloca_probe就是那个在栈中分配内存所使用到的函数。
我们由此得知,在栈中分配超过某个特定值的内存,就需要调用alloca函数。
(文章开头那本《30天自制操作系统》书中写的是4KB,但是我这里测试下来,似乎又不是4KB,这里暂时存疑)
3.手工调用alloca函数 我们这里尝试运行如下的代码:
#include "stdafx.h" #include #includeint a; int main(){ int b; int *p=(int*)alloca(sizeof(int)); printf("%p %p %p ",&a,&b,p); system("pause"); }

可以看出,输出的p的地址与b的地址更加相近。b写在main函数中,说明这是一个局部变量,或者叫做自动变量,它是保存在栈中的。由此,我们得知,alloca也是会分配在栈中。
4.注意事项 (1)alloca所分配的内存会被自动释放,不能free!!!
如果我们尝试使用free释放p的内存,在VS中,引发了一个运行错误。
【原创】浅谈指针(十一)alloca函数
文章图片

(2)alloca的可移植性不高,因此我们一般不使用它。
在调用alloca()的函数返回的时候,它分配的内存会自动释放。也就是说,用alloca()分配的内存在某种程度上局部于函数的堆栈帧或上下文中。
alloca()不具可移植性,而且在没有传统堆栈的机器上很难实现。当它的返回值直接传入另一个函数时会带来问题, 如 fgets(alloca(100), 100, stdin)。
(3)由于C99开始引入了可变长数组VLA,可以使用这个功能来更好地完成alloca所需要的完成的任务。

    推荐阅读