都知道内存管理分为1.申请过程 2. 释放过程
下面将要说明 malloc()[男主角] free()[女猪脚] realloc()[男二号] calloc()[男配角] (均包含在
void* malloc (size_t size);
指针的相减在连续的内存上才有意义; 申请后不进行初始化,内容为上次的残留内容;传入的参数为0,这是未定义行为!!
(size_t是unsigned long无符号长整型, 若传入的是负数, 则表现为很大的正数,单位是字节)
要注意的是: malloc()函数在使用的时候,可能存在申请失败(若内存太大,找不到连续的大内存空间时会申请失败),此时malloc()返回NULL指针.在使用前必须要使用判断NULL来判空!
void free (void* ptr);
在程序中,malloc申请的内存,必须要释放,否则会"内存泄漏",除非显式使用free来释放(与大括号无关),若程序中反复使用malloc申请内存,而没有使用free,那么会导致内存不足(也就是内存泄漏).
内存泄漏:会导致程序崩溃, 但是又不会立即崩溃, 就像定时炸弹,极难定位.
实用的测试方法:
1)如何判断程序中是否存在内存泄漏?
最好的办法是进行 稳定性测试, 也就是让被测试的逻辑重复执行几十万次,记录开始运行时程序占用的内存数,再记录结束时占用的内存数
2)若程序中出现内存泄漏, 如何定位问题出处?
a) 有一些内存泄漏检测工具(注意的是: 不一定好使),比较适用于小程序
b) 猜: 靠经验吃饭
c) 二分法: 把有些逻辑干掉
3)如果内存泄漏实在找不到问题出处, 怎么处理?
重启大法.简单粗暴,但又有效的方案.
内存泄漏的实例场景:
有些代码虽然有malloc, 也有free, 内存可能泄漏
有些代码虽然没有malloc,也有free, 内存可能泄漏
有些代码有malloc,虽然没配对的free.
若malloc的这个内存空间, 本来的生命周期就跟随整个程序, 并且也没有反复的去malloc.
内存泄漏的评判标准, 要看内存是否持续性上涨,主要是针对服务器(运行时间长),客户端程序还好.
void* calloc (size_t num, size_t size);
它的函数功能较malloc(), 在申请到的内存空间后,再进行初始化为全0, 并没有其他区别
但是在实际的应用场合,内存空间并不一定需要初始化为全0,如若这个内存空间需要存其他值时,只用calloc相当于多了冗余,这会影响到程序的性能.
void* realloc (void* ptr, size_t size);
函数功能:将曾经已经动态申请的内存空间, 扩容为新的容量空间.
局限性:要考虑后续的连续内存空间;
若后续的内存空间不足, 会放下扩容后的空间, 这种情况下,realloc会自动在内存中找到一块更大的连续内存空间, 把原本的内存中的数据拷贝过去,并释放原来的内存空间.
若出发扩容会导致大规模的拷贝内存(比较低效),它与malloc相比,不那么可控
一般不推荐使用realloc, 返回值和参数不一定相等