关于malloc的一些想法
之前一段时间翻阅过一些内存分配的资料,这次终于能将其整理记录下来了。
c标准库里有两个耳熟能详的函数,用于对堆空间的内存进行分配和释放,它们分别是:
- malloc。负责分配一个指定大小的一块内存给调用的程序,函数返回一个指向这块内存的指针。
- free。对函数参数指向的内存块进行释放操作。
需要说明的是,不管是malloc还是free,这些函数都是c标准库提供给我们的,而不是操作系统的API。对于堆上的内存管理,操作系统(Linux)提供以下两个接口:
- sbrk。用于扩张和收缩堆,本质上就是移动指向堆顶的指针。把指针向高地址移动就是在扩张堆、向低地址移动就是在收缩堆。
- mmap、munmap。用于内存映射和取消内存映射,对于大块的内存申请,直接调用mmap申请一个内存段更加高效。
显然,malloc的实现是基于操作系统提供的API的,也就是上面提到的那两个syscall。而且,一般考虑到会频繁的进行内存分配,我们往往希望能尽量减少syscall的次数。于是,通常的策略是如下。
一般地,实现会在内部维持了一个空闲内存块的链表,当我们通过malloc申请一块内存,我们先在这个链表里进行搜索,如果找到符合大小的内存块,就将这个内存块返回给调用程序。否则,当在空闲链表中搜索不到满足要求的内存块,说明当前堆的大小不够用了,调用syscall以扩张堆的大小,并重新搜索内存块。当通过free释放内存的时候,则将内存块返回给这个空闲链表。空闲链表可能会有一些策略,用来在未来的某一个时候,通过syscall将这些空闲的内存重新归还给操作系统。
不同的malloc/free的实现,主要是在如何组织这个空闲内存块的链表上有所不同。关于glibc的malloc可以参考这篇文章:Glibc内存管理。
在清楚malloc内部做了什么之后,就可以搞明白一些诡异的问题了。比如说,重现引用一块已经free掉的内存,为什么有时候会报段错误,有时候会崩溃,有时候什么事都没发生?
首先要说明的是操作系统的内存管理是段页式的,既分段也分页。而通常一个程序的内存段有:代码段、静态数据全局数据段、堆、栈等,而程序所能访问的地址必须是在OS已经分配的内存段中。如果访问的地址不在已存在的段内,就会报我们熟悉的段错误。当通过free将内存释放时,分配程序有可能为了重新利用这块内存而缓存着它,也有可能将这块内存真正的归还给操作系统。如果内存块被真正的归还给操作系统,比如free操作导致了堆的收缩,或是在free中调用了munmap取消了一个内存映射。这时候如果有一个指针指向这块内存地址,对它引用就会导致段错误。
不过大多数情况下,free掉的内存块不是立即归还给OS,而是被分配程序(malloc)插入到空闲内存块链表中缓存起来,等待再次被利用。有的实现(例如glibc的ptmalloc)为了内存空间的复用,会在这个内存块里面记录下指向链表前后节点的指针等信息。这时候如果我们对free掉的内存块重新执行写操作就有可能会改写这部分信息,导致这个内存块被写坏,破坏了空闲链表的结构,因此就有可能引起崩溃。
关于malloc的一些想法的更多相关文章
- C——malloc & free(转载自bccn C语言论坛)
原帖及讨论:http://bbs.bccn.net/thread-82212-1-1.html 原文链接:http://www.bccn.net/Article/kfyy/cyy/jszl/20060 ...
- 浅谈C中的malloc和free
转自http://bbs.bccn.net/thread-82212-1-1.html非常感谢作者 浅谈C中的malloc和free 在C语言的学习中,对内存管理这部分的知识掌握尤其重要!之前对C中的 ...
- C语言二重指针与malloc
(内容主要源于网上,只是加入了些自己的剖析) 假设有一个二重指针: char **p; 同时有一个指针数组 char *name[4]; 如何引用p呢? 首先我们有程序代码如下 #include &l ...
- (转)Free函数的参数一定要是malloc返回的那个指针
Free函数的参数一定要是malloc返回的那个指针 之前认为只要free的参数在malloc分配的区域之内就可以了, 现在发现不对的.在嵌入式里分配堆都是按照块来的,只要在这个块内系统就能识别, ...
- 关于malloc和free函数的用法
原文:http://blog.pfan.cn/vfdff/33507.html 个人总结 在C语言的学习中,对内存管理这部分的知识掌 握尤其重要!之前对C中的malloc()和free()两个函数的了 ...
- 数据结构基础——指针及动态内存分配(malloc)
一.指针 C语言中的指针是一种数据类型,比如说我们用int *a;就定义了一个指针a,它指向一个int类型的数.但是这个指针是未初始化的,所以,一般的,我们都在创建指针时初始化它,以免出错,在还不吃的 ...
- new与malloc的区别,以及内存分配浅析
从函数声明上可以看出.malloc 和 new 至少有两个不同: new 返回指定类型的指针,并且可以自动计算所需要大小.比如: 1 2 3 int *p; p = new int; //返回类型 ...
- C语言中 malloc函数用法
一.malloc()和free()的基本概念以及基本用法: 1.函数原型及说明: void *malloc(long NumBytes):该函数分配了NumBytes个字节,并返回了指向这块内存的指针 ...
- malloc&&free的系统运行机制及其源代码的理解
一.malloc()和free()的基本概念以及基本用法: 1.函数原型及说明: void *malloc(long NumBytes):该函数分配了NumBytes个字节,并返回了指向这块内存的指针 ...
随机推荐
- matlab画柱状图
论文中需要画图进行比较,感觉还是matlab画起来比较方便,先把自己画的图及matlab代码放上. y=[300 311;390 425; 312 321; 250 185; 550 535; 420 ...
- C# 自动Ping服务
using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; u ...
- System.map文件【转】
转自:http://blog.csdn.net/david104/article/details/7194185 当运行GNU链接器gld(ld)时若使用了"-M"选项,或者使用n ...
- 搜索引擎LuceneNet
http://www.cnblogs.com/edisonchou/p/5348625.html
- Bash:-set设置位置变量结合while和shift使用
#!/bin/bash aaa=( ) bbb=(a b c d) set -- ${aaa[@]} ));do } shift done set -- echo "------------ ...
- .md文件的语法
md全称是Macdown,.md文件可以当记事本一样使用,作为编辑软件,还可以自己添加样式,图片,链接等,可以用记事本打开,也可以保持样式排版转换为html文件,语法比较简单..md除了编辑容易的优势 ...
- 学习C语言感悟
还记得刚上第一节C语言课的时候,基本上一节课只有最后10分钟的内容听懂了.在此之前从没接触过C语言,想说看看书预习一下吧,可是完全找不到条理,发现老师也不是按书上的顺序讲的.当时就特别着急,想说难道 ...
- wf(六)
前面我们都是通过WorkflowInvoker这个类来调用方法的,这种方式是很简单的,因为这是同步的而且同样的调用者调用工作流使用的线程是一样的. 另外一个调用工作流的方法是通过工作流应用程序类(Wo ...
- GOLANG 基本数据类型 整型
基本数据类型-整型 种类 有符号(负号) int8 int16 int32 int64 无符号(无符号) uint8 uint16 uint32 uint64 架构特定(取决于系统位 ...
- $.ajax()方法所有参数详解;$.get(),$.post(),$.getJSON(),$.ajax()详解
[一]$.ajax()所有参数详解 url: 要求为String类型的参数,(默认为当前页地址)发送请求的地址. type: 要求为String类型的参数,请求方式(post或get)默认为get.注 ...