C语言malloc和free实现原理

本文解析了C语言中malloc和free函数在Debug与Release版本的不同实现。详细介绍了内存分配与释放的过程,包括内存头部结构、校验位的作用以及系统API的调用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原贴地址:点击打开链接

以下是一段简单的C代码,malloc和free到底做了什么?


int main()  
{  
    char* p = (char*)malloc(32);  
    free(p);  
    return 0;  
}  
malloc和free的debug和release版本实现各不相同,而且相差很大。


Debug版本
malloc需要分配的内存会比实际的size多36byte。最终分配的内存块如下:


_CrtMemBlockHeader是一个双向链表结构,其定义如下:


<pre name="code" class="cpp">typedef struct _CrtMemBlockHeader  
{  
    struct _CrtMemBlockHeader *pBlockHeaderNext;    //下次分配的内存块  
    struct _CrtMemBlockHeader *pBlockHeaderPrev;    //上次分配的内存块  
    char *szFileName;               //分配内存代码的文件名  
    int nLine;                  //分配内存代码的行号  
    size_t nDataSize;               //请求的大小,如实例中的32  
    int nBlockUse;                  //请求的内存类型,如实例中的user类型  
    long lRequest;                  //请求id,每次请求都会被记录  
    unsigned char gap[nNoMansLandSize];     //4字节校验位  
} _CrtMemBlockHeader;  


用户请求内存前后分别有4字节的校验位,分配内存后都会被初始化为0xFD。如果这8个字节被改写,free时就会触发断言失败。
而请求的32字节会被初始化为0xCC(和栈的初始化一样)。
系统通过记录这些信息就能显示的给出错误。比如越界访问请求的内存在debug下会断言失败,release下面则不会,从而这会给程序埋下巨大的隐患。很多在release下偶发的错误就是这样产生的。
_CrtMemBlockHeader总共32字节,加上用户请求的32字节及最后4字节校验位是68字节。最终调用系统的API请求内存。比如Windows下面是HeapAlloc。


如果内存分配失败,malloc不像new那样可以调用new_handler来处理,它直接返回NULL。


free则是对_CrtMemBlockHeader的信息做清理操作,检查校验位等等。最终调用系统API释放内存。比如Windows下面是HeapFree。


Release版本
实际分配的内存等于请求的内存大小。malloc和free只是在系统API之上做了些判断操作。


总结
C语言是跨平台的,最终的内存处理都是交给系统API完成。系统会记录每一块分配内存的地址,大小,释放情况等等。所以free时只需要传一个地址的参数就可以了。而且同一个地址不能释放两次。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值