从汇编层次理解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并不都是可⽤空间,其中操作系统要占⽤⼀部分。所以不要盲⽬的去开辟空间。
下⾯来看⼀个简单的开辟空间:
molloc函数从汇编⾓度来看(这⾥不讨论malloc函数是如何执⾏的):
第⼀次开辟空间:
第⼆、三次开辟空间:
malloc开辟的空间是以够⽤为主,⽽不是越多越好,避免空间浪费。
注意⼀:
⽐如说很多⼈喜欢这么玩,啥也不说,先循环来个100万个,丝毫没有意义第⼀次开辟⼀个char ⼤⼩的空间第⼆次开辟⼀个int ⼤⼩的空间第三次开辟⼀个10个int ⼤⼩的空间
1
2
3
4
5esp 记录的是栈底的位置最左侧的是地址值,可以看到是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;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15可以看到与第⼀次不同的仅仅是第⼆⾏push 后⾯的数字不同,那么这⾏代码是什么意思呢?
函数调⽤前,是通过push 来传递参数的,可以看到这三次分别是1、4、28h ,正好是这三次开辟空间的⼤⼩,28h 是16进制,转换成10进制为40. 1
2 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 ; }
1
2
3
4
5
6
7
8
9
10
注意⼆:⽐如不注意开辟的类型
注意三:不释放int *p =(int *)malloc (sizeof *(100));for (int i =0;i <100;++i ){p [i ]=i ;}free (p );p =NULL ;以为强转成为int 型指针⾥⾯就能够放100个int 型数据,结果直接卡死sizeof ()⾥⾯放的是字节数,int 类型的数据是4个字节,因为100个字节⼤⼩只能放50个int 数据。所以访问第51个的时候就越界了因此我开辟时候都是⽤sizeof (数据类型)*个数来写,清晰明了1
2
3
4
5
6
7
8
9
10int *p =(int *)malloc (sizeof *(100));for (int i =0;i <100;++i ){p [i ]=i ;}⼿动开辟的空间必须释放,你不释放的话会⼀直存在,⼀直到程序结束.同时⼀个空间也不能多次释放。1
2
3
4
5
6
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论