内存泄漏
指由于疏忽或错误造成程序未能释放已经不再使用的内存的情况。内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,导致在释放该段内存之前就失去了对该段内存的控制,从而造成了内存的浪费。
导致内存泄漏的原因大多分为以下几个情况
1.未初始化的内存
char *p = malloc ( 10 );
p
已被分配了 10 个字节。这 10 个字节可能包含垃圾数据 某个代码段尝试访问它,则可能会获得垃圾值。
您的程序可能具有不可预测的行为。p
可能具有您的程序从未曾预料到的值。
良好的实践是始终结合使用 memset
和 malloc
,或者使用 calloc
。
char *p = malloc (10); memset(p,’\0’,10);
现在,即使同一个代码段尝试在对 p
赋值前访问它,该代码段也能正确处理 Null
值(在理想情况下应具有的值),然后将具有正确的行为。
2.内存覆盖
3.读取越界
内存读取越界 (overread) 是指所读取的字节数多于它们应有的字节数。
4.未及时释放动态申请的堆内存
#include <stdlib.h> #include <iostream> using namespace std; void GetMemory(char *p, int num) { p = (char*)malloc(sizeof(char) * num);//使用new也能够检测出来 } int main(int argc,char** argv) { char *str = NULL; GetMemory(str, 100); cout<<"Memory leak test!"<<endl; //如果main中存在while循环调用GetMemory //那么问题将变得很严重 //while(1){GetMemory(...);} return 0; }
总结良好的实践是:
- 始终结合使用memset和 malloc,或始终使用calloc。
- 每当向指针写入值时,都要确保对可用字节数和所写入的字节数进行交叉核对。
- 在对指针赋值前,要确保没有内存位置会变为孤立的。
- 每当释放结构化的元素(而该元素又包含指向动态分配的内存位置的指针)时,都应首先遍历子内存位置并从那里开始释放,然后再遍历回父节点。
- 始终正确处理返回动态分配的内存引用的函数返回值。
- 每个malloc 都要有一个对应的 free。
- 确保您不是在访问空指针。