malloc()与free()

函数原型

malloc函数的函数原型为:void* malloc(unsigned int size),它根据参数指定的尺寸来分配内存块,并且返回一个void型指针,指向新分配的内存块的初始位置。如果内存分配失败(内存不足),则函数返回NULL。

关于返回值

malloc的返回值为void*。我们在使用的时候,习惯对返回值进行强制类型转换:

char * p = NULL;

p = (char *)malloc(sizeof(char));

ANSI C以前的C,因为没有void*这种类型,malloc函数的返回值被简单地定义为char*,char*是不能被赋予指向其他类型变量的指针的。所以在使用malloc函数时通常需要对其返回值进行强制类型转换。

在ANSI C中,malloc函数的返回值为void*。void*类型是可以直接赋值给其他任何类型的指针。所以,上面的强制类型转换操作现在已经不需要了。

然而在c++中,任何类型的指针都可以赋给void*,而void*却不可以赋给其他类型的指针,所以在c++中使用malloc函数的时候,强制类型转换是必须的。另一方面,在c++中应该使用new来分配内存。

malloc在堆上分配内存

malloc函数分配的内存是在堆(heap)上的。操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时,会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序,另外,对于大多数系统,会在这块内存空间中的首地址处记录本次分配的大小,这样代码中的delete或free语句才能正确的释放本内存空间。我们常说的内存泄露,最常见的就是堆泄露(还有资源泄露),它是指程序在运行中出现泄露,如果程序被关闭掉的话,操作系统会帮助释放泄漏的内存。

malloc的使用

malloc函数使用起来倒是挺简单的,主要的使用范例有两种:一是动态分配结构体,通常用于被称为“链表”的数据结构中;二是分配可变长度的数组。对这两种用法就不多说了,主要是来看使用过程中的注意点:

  1. 调用malloc函数后,应该对函数返回值进行检查。前面说过,内存分配一旦失败,malloc()会返回NULL。
    1. char * p = NULL;
    2. p = (char *)malloc(sizeof(char));
    3. if(!p)
    4. exit(1);
  2. 在程序结束时,应该调用free函数对malloc函数分配的内存进行释放。

实际上,c语言标准没有规定要这么做,而且普通的PC上的操作系统,在进程结束时,肯定会释放曾经分配给当前进程的内存空间,也就是说,在程序结束之前,没有必要调用free()。但是,对于一串连续的程序处理事件,如果先前程序分配的内存没有及时释放掉,那后面的工作就遭殃了。所以”malloc与free配套出现”还是相当合理的。

malloc()与free( )

从操作系统一次性地取得比较大的内存,当程序调用malloc()时,malloc()便将内存”零售”给应用程序,这是malloc()的大体实现。而当这块一次性取出来的内存不够用的时候,就请求操作系统对空间进行扩容。多次调用malloc()(导致内存不够用了)会调用一次brk(),内存区域向地址较大的一方伸长。malloc()分配内存,会用到brk(用于小内存申请<=128kb,在堆上)或mmap2(用于大内存申请,一般是堆和栈中间)系统调用 。

K&R中记录了malloc()最简单的一种实现方式:通过链表来实现。malloc管理的空间不一定是连续的,空闲存储空间以空闲块链表的方式组织。在这种方式下,每个块之前都加上了一个管理区域,包含一个长度、一个指向下一块的指针以及一个指向自身存储空间的指针。这些快按照储存地址的升序组织。最后一块(最高地址)指向第一块。这里使用K&R中的图加以说明:

当有申请要求时,malloc将扫描空闲块链表,直到找到一块足够大的空闲块为止,如果找不到,则向操作系统申请一个大块并加入到空闲链表中。然而在这种内存管理方式的运行环境中,一旦数组越界检查发生错误,越过了malloc()分配的内存区域写入了数据,将会破坏下一个块的管理区域,容易造成程序崩溃。在《UNIX环境高级编程》中有一段话肯定了以上的说法:

“大多数实现所分配的存储空间比所要求的要稍大一些,额外的空间用来记录管理信息——分配块的长度,指向下一个分配块的指针等等。这就意味着如果写过一个已分配区的尾端,则会改写后一块的管理信息。这种类型的错误是灾难性的,但是因为这种错误不会很快就暴露出来,所以也就很难发现。将指向分配块的指针向后移动也可能会改写本块的管理信息。”

那么,free()在这里做了什么呢?free()将管理区域的标记改为”空块”,顺便也将上下空块合并成一个块,这样也防止了块的碎片化。这么说来,free()函数在调用后,对应的内存是不会立刻返还给操作系统的(还在空闲链表里呆着)。也就是说,调用了free()之后,对应内存的内容不会马上被破坏,直到该块内存被重新分配,里面的内容才会被覆盖重写。尽管如此,调用free()之后,是不能引用对应的内存区域的。所以仓促地使用free()是不对的,特别是当有两个指针指向同一块内存时,指针1把内存释放了,而指针2还指向那块内存,然而指针2已经不能进行解引用了。

这么看来,free()函数实际上并没有做”释放”的实际操作,它只是改变一些状态,告知操作系统某块内存可以去释放。至于如何告诉,还需要后续了解。

浅谈malloc()与free()的更多相关文章

  1. 从内部入手,浅谈malloc和new的区别

    想要理解一样事物,就要先用自己的语言去描述一件事物.在我查阅资料后,发现malloc函数简单说来就是空闲内存空间收集器,并把空闲空间关联起来,用术语来说就是:将空闲内存块合并起来并称为"闲置 ...

  2. 浅谈malloc()和free()工作原理

    编程之路刚刚开始,错误难免,希望大家能够指出.  malloc()和free()是我经常需要用到的函数,一般情况下,C程序使用malloc()在堆上分配内存,free()释放内存,两者的参数和返回值就 ...

  3. 浅谈malloc/free和new/delete 的区别

    malloc和new的区别 malloc是库函数,需要包头文件才能成功运行编译:new是操作符(C++中的关键字),需要在C++的环境下使用. malloc既可以在C语言中使用也可以在C++中使用,n ...

  4. 浅谈C中的malloc和free

    转自http://bbs.bccn.net/thread-82212-1-1.html非常感谢作者 浅谈C中的malloc和free 在C语言的学习中,对内存管理这部分的知识掌握尤其重要!之前对C中的 ...

  5. (转)浅谈C中的malloc和free

    原帖及讨论:http://bbs.bccn.net/thread-82212-1-1.html 在C语言的学习中,对内存管理这部分的知识掌握尤其重要!之前对C中的malloc()和free()两个函数 ...

  6. 浅谈new operator、operator new和placement new 分类: C/C++ 2015-05-05 00:19 41人阅读 评论(0) 收藏

    浅谈new operator.operator new和placement new C++中使用new来产生一个存在于heap(堆)上对象时,实际上是调用了operator new函数和placeme ...

  7. java反射机制浅谈

    一.Java的反射机制浅谈 最近研究java研究得很给力,主要以看博文为学习方式.以下是我对java的反射机制所产生的一些感悟,希望各位童鞋看到失误之处不吝指出.受到各位指教之处,如若让小生好好感动, ...

  8. java的反射机制浅谈(转)

    原文链接:java的反射机制浅谈 一.java的反射机制浅谈 1.何谓反射机制 根据网文,java中的反射机制可以如此定义: JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性 ...

  9. C学习笔记(11)--- 可变参数,浅谈内存管理 【C基础概念系列完结】

    1.可变参数(variable arguments): 可变参数允许您定义一个函数,能根据具体的需求接受可变数量的参数. int func(int, ... )             (函数 fun ...

随机推荐

  1. 【转】【MySql】Waiting for table metadata lock原因分析

    MySQL在进行alter table等DDL操作时,有时会出现Waiting for table metadata lock的等待场景.而且,一旦alter table TableA的操作停滞在Wa ...

  2. T138

    这一列车. 十年前送我去西安, 十年后搭我返故乡. 十年前手拉着手儿, 十年后独对着车窗.   这一列车. 装饰着坚毅的中国蓝, 却失去了往日光环. 只有通往偏远.落后的地方, 只有没赶上高铁动车的行 ...

  3. ASP.NET 中执行 URL 重写

    具体实现步骤(其中的一种实现方法): 一.下载相关的DLL(ActionlessForm.dll和UrlRewriter.dll) http://download.csdn.net/detail/yi ...

  4. HTML5添加 video 视频标签后仍然无法播放的解决方法 IIS添加MIEI类型

    现象:插入如下代码后仍然无法看视频(注:视频已确认为浏览器支持格式) <video controls="controls" width="500px" h ...

  5. [转]一篇很全面的freemarker教程

    copy自http://demojava.iteye.com/blog/800204 以下内容全部是网上收集: FreeMarker的模板文件并不比HTML页面复杂多少,FreeMarker模板文件主 ...

  6. CSS3 3D骰子

    z zz zz zzzz zzzzz zzzzzz

  7. SharePoint GroupedItemPicker Control

    这个控件SharePoint用来选择Field ,和Content Type, 以下是一个完整的示例. <SharePoint:GroupedItemPicker ID="Select ...

  8. Ros集成开发环境配置

    参考资料: http://blog.csdn.net/yangziluomu/article/details/50848357 ROS使用IDE Eclipse http://blog.csdn.ne ...

  9. leetcode-Warm Up Contest-Aug.21

    leetcode   地址: https://leetcode.com/contest/detail/1 (1)-- Lexicographical Numbers Given an integer  ...

  10. iOS -- autoResizingMask使用(转)

    autoResizingMask 是UIView的一个属性,在一些简单的布局中,使用autoResizingMask,可以实现子控件相对于父控件的自动布局. autoResizingMask 是UIV ...