从汇编层次理解malloc函数

很多新手练习malloc都喜欢用一个for循环开辟一个堆空间,大多时候会直接卡死,而有不知道是什么原因造成的。就会很困惑,如果你也有此困惑,那么就耐心的看下去。

一个32位的cpu有32位,八位是一个字节,总共是四个字节,用十六进制表示就是0x00 00 00 00,cpu是通过寻址来操作的,32位(最大数2的32次方)的最大地址值为0xFF FF FF FF,最小地址值为0x00 00 00 00,每一个应用程序都会分到一个4GB(2的32次方)大小的虚拟空间(并不是真实的),这也是为什么32位cpu最大支持4GB的原因。当然了4GB并不都是可用空间,其中操作系统要占用一部分。所以不要盲目的去开辟空间。

下面来看一个简单的开辟空间:
从汇编层次理解malloc函数_第1张图片

第一次开辟一个char大小的空间

第二次开辟一个int大小的空间

第三次开辟一个10int大小的空间

从汇编角度来看(这里不讨论malloc函数是如何执行的):

从汇编层次理解malloc函数_第2张图片

第一次开辟空间:

esp记录的是栈底的位置
最左侧的是地址值,可以看到是32位(十六进制)

mov esi,esp是把esp的值给esi

push 1是吧1压入栈中,也证实了char大小是一个字节,push会把esp地址值减4(栈空间是向下增长的)

call...是执行了开辟空间的函数

add esp,4,地址值加4,恢复堆栈平衡

cmp esi,esp查看是否堆栈平衡
call ...这个函数是编译器给我加的,查看堆栈平衡的

mov dword ptr [p1],eax 把结果给p1;

第二、三次开辟空间:

可以看到与第一次不同的仅仅是第二行push 后面的数字不同,那么这行代码是什么意思呢?
函数调用前,是通过push来传递参数的,可以看到这三次分别是1428h,正好是这三次开辟空间的大小,28h是16进制,转换成10进制为40. 

malloc开辟的空间是以够用为主,而不是越多越好,避免空间浪费。

注意一:

比如说很多人喜欢这么玩,啥也不说,先循环来个100万个,丝毫没有意义

	for (int i = 0; i < 1000000; i++)
	{
		int* p = (int *)malloc(sizeof(int) * 1000);
		for (int j = 0; j < 1000; ++j)
		{
			p[j] = j;
		}
		free(p);
		p=NULL;
	}

注意二:比如不注意开辟的类型

int *p=(int*)malloc(sizeof*(100));
for(int i=0;i<100;++i)
{
p[i]=i;
}
free(p);
p=NULL;
以为强转成为int型指针里面就能够放100int型数据,结果直接卡死
sizeof()里面放的是字节数,int类型的数据是4个字节,因为100个字节大小只能放50int数据。所以访问第51个的时候就越界了
因此我开辟时候都是用sizeof(数据类型)*个数来写,清晰明了

注意三:不释放

int *p=(int*)malloc(sizeof*(100));
for(int i=0;i<100;++i)
{
p[i]=i;
}
手动开辟的空间必须释放,你不释放的话会一直存在,一直到程序结束.同时一个空间也不能多次释放。

你可能感兴趣的:(c\c++)