> 文章列表 > malloc的一些知识

malloc的一些知识

malloc的一些知识

        这是一个叫malloc的家伙,一直勤勤恳恳帮你为所欲为的玩转系统内存。可是长路漫漫,唯malloc作伴,我却不懂它。走近malloc,多了解一下总没错。

可能对我们来讲,malloc就是void* malloc (size_t len),调用就是了,实际glic源码太太太大了,如下:

 

今天就了解三个感兴趣的问题:

第一个灯下黑的问题:

1、memset申请到的内存是连续的吗?

        不一定是连续的。malloc出来的空间,只是在虚拟内存中是连续的。而从实际的物理空间到虚拟内存空间还有一个映射的关系。这个映射是由操作系统来控制的,一般情况下,从虚拟地址无法反查到物理地址。对于连续的虚拟地址空间,也就无法得知是否物理连续。但由于映射的不确定性,当申请一段内存空间,尤其是比较大的内存长度情况下,物理地址不连续的可能性还是相当大的。

2、malloc和calloc的区别

void* calloc (size_t n, size_t len);void* malloc (size_t len)

        显然从函数接口可以看出malloc和calloc的参数个数是不同,其中malloc中的len为程序所需的总的大小,calloc中的两个参数分别代表所要申请元素的个数以及单个元素的大小。即n*len为申请的总的大小。

        除了参数上区别,两者的处理机制也是不同的,malloc不会对当前申请出来的内存进行初始化操作,即动态分配完内存后里面的数据是随机数,所以我们在调试程序时,单步或者断点到刚分配的内存这里是一串霍金都看不懂的东西。而calloc不同,不仅会分配内存,还会在分配内存后进行初始化为0的操作。也正是因为多了这个初始化的操作,calloc的效率不如malloc,这也就顺带解答了另外一个疑惑,就是为什么工程中用的malloc较多,而不是calloc,因为很多时候的malloc内存并不需要初始化这一步,如果需要加一个memset也就解决了。

返回值上也是有区别的,malloc的返回值是一个对象,而calloc的返回是一个数组。

3、malloc和memset的效率谁更高?

先说OS内存分配过程,如下:

用户态程序使用malloc接口,分配虚拟地址。

用户程序访问该虚拟地址,比如memset。

硬件(MMU)需要将虚拟地址转换为物理地址。

硬件读取页表。

硬件发现相应的页表项不存在,硬件自动触发缺页异常。

硬件自动跳转到page fault的处理程序(内核实现注册好)

内核中的page fault处理程序执行,在其中分配物理内存,然后修改页表(创建页表项)

异常处理完毕,返回程序用户态,继续执行memset相应的操作。

至此,虚拟内存和物理内存都分配完成,并完成映射。另一个角度看,如果malloc分配内存后,一直不使用,那就一直不会分配物理内存,这种内存分配策略叫延迟分配

这是memset:

void * memset (void * p,int c,size_t n);

从指针的头部p开始,为每个字节赋值c,操作的长度为n,memset是以字节为单位进行赋值的,所赋值的范围是0x00~0xFF。

测试memset和malloc的执行效率:

  1. 分配1万个100字节block,1ms。
  2. 分配1万个100字节block + memest 1ms
  3. 分配1万个500字节block,3ms
  4. 分配1万个500字节block + memest,3ms
  5. 分配100万个500字节block, 322ms
  6. 分配100万个500字节block + memset, 333ms

由此可见,在分配的字节块变大且变多的时候,memset是耗时的,但是比malloc效率高。