标签:
从用户使用程序的角度来看,内存泄漏本身不会产生什么危害,作为一般的用户,根本感觉不到内存泄漏的存在。真正有危害的是内存泄漏的堆积,这会最终消耗尽系统所有的内存。主要有以下几种表现形式:
在我们写程序的时候,一般会使用malloc,realloc,new等函数从堆中分配到一块内存,使用完后,程序必须负责相应的调用free或delete释放该内存块,否则,这块内存就不能被再次使用,我们就说这块内存泄漏了。如果要避免这个问题,还是要从代码上入手,良好的编码习惯和规范,是避免错误的不二法门。
第一:良好的编码习惯,尽量在涉及内存的程序段,检测出内存泄露。当程式稳定之后,在来检测内存泄露时,无疑增加了排除的困难和复杂度。使用了内存分配的函数,一旦使用完毕,要记得要使用其相应的函数释放掉。
Heap memory:
malloc\realloc ------ free
new \new[] ---------- delete \delete[]
GlobalAlloc------------GlobalFree
要特别注意数组对象的内存泄漏
MyPointEX *pointArray =new MyPointEX [100];
其删除形式为:
delete []pointArray ;
第二:将分配的内存的指针以链表的形式自行管理,使用完毕之后从链表中删除,程序结束时可检查改链表。
第三:Boost 中的smart pointer。
第四:一些常见的工具插件,如ccmalloc、Dmalloc、Leaky等等。
我主要想结合代码讲讲第二个方法,设计思想其实很简单,用到STL中的list。可能有人要问,为什么不用vector呢?
list和vector的区别如下:
vector为存储的对象分配一块连续的地址空间,因此对vector中的元素随机访问效率很高。在vecotor中插入或者删除某个元素,需要将现有元素进行复制,移动。如果vector中存储的对象很大,或者构造函数复杂,则在对现有元素进行拷贝时开销较大,因为拷贝对象要调用拷贝构造函数。对于简单的小对象,vector的效率优于list。vector在每次扩张容量的时候,将容量扩展2倍,这样对于小对象来说,效率是很高的。
list中的对象是离散存储的,随机访问某个元素需要遍历list。在list中插入元素,尤其是在首尾插入元素,效率很高,
只需要改变元素的指针。
vector适用:对象数量变化少,简单对象,随机访问元素频繁
list适用: 对象数量变化大,对象复杂,插入和删除频繁
#include <iostream> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <list> using namespace std; const int nMaxSize = 26; struct Node { int count; Node *next[nMaxSize]; }; Node *root = NULL; list <Node *> nodeMemory; void TreeCreate() { root = (Node *)malloc(sizeof(Node)); for (int i = 0; i < nMaxSize; ++i) { root->next[i] = NULL; } } void TreeInsert(char *pStr) { int i, j, len = strlen(pStr); Node *p = root; Node *q = NULL; for (i = 0; i < len; ++i) { int id = pStr[i] - ‘a‘; if (p->next[id] == NULL) { q = (Node *)malloc(sizeof(Node)); if(q != NULL) nodeMemory.push_back(q); q->count = 0; for (j = 0; j < nMaxSize; ++j) { q->next[j] = NULL; } p->next[id] = q; } p->next[id]->count++; p = p->next[id]; } } int TreeQuery(char *pStr) { int i, len = strlen(pStr); int id = 0; Node *p = root; for (i = 0; i < len; ++i) { id = pStr[i] - ‘a‘; p = p->next[id]; if (p == NULL) return 0; } return p->count; } void TreeDelete(Node *p) { if (p == NULL) return ; for (int i = 0; i < nMaxSize; ++i) { TreeDelete(p->next[i]); } nodeMemory.remove(p); free(p); p = NULL; } int main(int argc, char **argv) { char szBuffer[16]; int res = 0; TreeCreate(); int n = 3; while (n) { gets(szBuffer); if (strlen(szBuffer) == 0) break; TreeInsert(szBuffer); n--; } /* scanf("%s", szBuffer); res = TreeQuery(szBuffer); printf("%d\n", res); */ for(list<Node *>::iterator it = nodeMemory.begin();it != nodeMemory.end();it++) { cout<<*it<<endl; } cout<<nodeMemory.size()<<endl; TreeDelete(root); if(nodeMemory.empty()) cout<<"has delete the tire tree"<<endl; cout<<nodeMemory.size()<<endl; system("pause"); return 0; }
代码很简单,list存储的是指向内存空间的指针,每次malloc之后会把这个分配的内存指针push到list中,而当free之后,list的就会删除相应的内容,如果全释放掉了,则list变为空,从而可以判断使用后的内存是否全部释放掉了?
标签:
原文地址:http://www.cnblogs.com/shouce/p/5445020.html