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

前言

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

alloca函数

1.简介

之前看《30天自制操作系统》的时候,看见了这样一个东西:

没错,这就是alloca函数。

2.反汇编看alloca

现在,我们把VS打开,看看反汇编是如何的:
(顺便说一下反汇编的方法,就是下两个断点,如图)

然后左上角就会出现反汇编的页面,点进去

代码如下:

#include "stdafx.h"
#include<stdio.h>
#include<iostream>
#define N 100
int main(){
	char a[N];
	for(int i=1;i<=N;i++){
		a[i]=0;
	}
}

反汇编的结果是:

push        ebp  
004D1381 8B EC                mov         ebp,esp  
004D1383 81 EC 3C 01 00 00    sub         esp,13Ch  
004D1389 53                   push        ebx  
004D138A 56                   push        esi  
004D138B 57                   push        edi  
004D138C 8D BD C4 FE FF FF    lea         edi,[ebp-13Ch]  
004D1392 B9 4F 00 00 00       mov         ecx,4Fh  
004D1397 B8 CC CC CC CC       mov         eax,0CCCCCCCCh  
004D139C F3 AB                rep stos    dword ptr es:[edi]  
004D139E A1 00 70 4D 00       mov         eax,dword ptr [___security_cookie (4D7000h)]  
004D13A3 33 C5                xor         eax,ebp  
004D13A5 89 45 FC             mov         dword ptr [ebp-4],eax  

似乎看不出什么名堂来,但是如果一旦我们把N改为更大的数字,例如100000,再来看看:

00FF1380 55                   push        ebp  
00FF1381 8B EC                mov         ebp,esp  
00FF1383 B8 78 87 01 00       mov         eax,18778h  
00FF1388 E8 30 FE FF FF       call        @ILT+440(__alloca_probe) (0FF11BDh)  
00FF138D 53                   push        ebx  
00FF138E 56                   push        esi  
00FF138F 57                   push        edi  
00FF1390 8D BD 88 78 FE FF    lea         edi,[ebp-18778h]  
00FF1396 B9 DE 61 00 00       mov         ecx,61DEh  
00FF139B B8 CC CC CC CC       mov         eax,0CCCCCCCCh  
00FF13A0 F3 AB                rep stos    dword ptr es:[edi]  
00FF13A2 A1 00 70 FF 00       mov         eax,dword ptr [___security_cookie (0FF7000h)]  
00FF13A7 33 C5                xor         eax,ebp  
00FF13A9 89 45 FC             mov         dword ptr [ebp-4],eax 

看第四行,有一个叫做 call @ILT+440(__alloca_probe)的一个东西,
汇编语言中,call指令后面跟的东西是一个函数,那么alloca_probe就是那个在栈中分配内存所使用到的函数。
我们由此得知,在栈中分配超过某个特定值的内存,就需要调用alloca函数。
(文章开头那本《30天自制操作系统》书中写的是4KB,但是我这里测试下来,似乎又不是4KB,这里暂时存疑)

3.手工调用alloca函数

我们这里尝试运行如下的代码:

#include "stdafx.h"
#include<stdio.h>
#include<iostream>

int 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中,引发了一个运行错误。

(2)alloca的可移植性不高,因此我们一般不使用它。
在调用alloca()的函数返回的时候,它分配的内存会自动释放。也就是说,用alloca()分配的内存在某种程度上局部于函数的堆栈帧或上下文中。
alloca()不具可移植性,而且在没有传统堆栈的机器上很难实现。当它的返回值直接传入另一个函数时会带来问题, 如 fgets(alloca(100), 100, stdin)。

(3)由于C99开始引入了可变长数组VLA,可以使用这个功能来更好地完成alloca所需要的完成的任务。

posted @ 2022-03-26 09:59  计算机知识杂谈  阅读(1508)  评论(0编辑  收藏  举报