從用戶使用程序的角度來看,內存洩漏本身不會產生什麼危害,作為一般的用戶,根本感覺不到內存洩漏的存在。真正有危害的是內存洩漏的堆積,這會最終消耗盡系統所有的內存。主要有以下幾種表現形式:
1)cpu資源耗盡:估計是機器沒有反應了,鍵盤,鼠標,以及網絡等等。這個在windows上經常看見,特別是中了毒。 2)進程id耗盡:沒法創建新的進程了,串口或者telnet都沒法創建了。 3)硬盤耗盡: 機器要死了,交換內存沒法用,日志也沒法用了,死是很正常的。在我們寫程序的時候,一般會使用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適用: 對象數量變化大,對象復雜,插入和刪除頻繁
1 #include <iostream> 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <string.h> 5 #include <list> 6 7 using namespace std; 8 9 const int nMaxSize = 26; 10 struct Node 11 { 12 int count; 13 Node *next[nMaxSize]; 14 }; 15 Node *root = NULL; 16 list <Node *> nodeMemory; 17 18 void TreeCreate() 19 { 20 root = (Node *)malloc(sizeof(Node)); 21 for (int i = 0; i < nMaxSize; ++i) 22 { 23 root->next[i] = NULL; 24 } 25 } 26 27 void TreeInsert(char *pStr) 28 { 29 int i, j, len = strlen(pStr); 30 Node *p = root; 31 Node *q = NULL; 32 for (i = 0; i < len; ++i) 33 { 34 int id = pStr[i] - 'a'; 35 if (p->next[id] == NULL) 36 { 37 q = (Node *)malloc(sizeof(Node)); 38 if(q != NULL) 39 nodeMemory.push_back(q); 40 q->count = 0; 41 for (j = 0; j < nMaxSize; ++j) 42 { 43 q->next[j] = NULL; 44 } 45 p->next[id] = q; 46 } 47 p->next[id]->count++; 48 p = p->next[id]; 49 } 50 } 51 52 int TreeQuery(char *pStr) 53 { 54 int i, len = strlen(pStr); 55 int id = 0; 56 Node *p = root; 57 for (i = 0; i < len; ++i) 58 { 59 id = pStr[i] - 'a'; 60 p = p->next[id]; 61 if (p == NULL) return 0; 62 } 63 return p->count; 64 } 65 66 void TreeDelete(Node *p) 67 { 68 if (p == NULL) 69 return ; 70 for (int i = 0; i < nMaxSize; ++i) 71 { 72 TreeDelete(p->next[i]); 73 } 74 nodeMemory.remove(p); 75 free(p); 76 p = NULL; 77 } 78 79 int main(int argc, char **argv) 80 { 81 char szBuffer[16]; 82 int res = 0; 83 TreeCreate(); 84 int n = 3; 85 while (n) 86 { 87 gets(szBuffer); 88 if (strlen(szBuffer) == 0) 89 break; 90 TreeInsert(szBuffer); 91 n--; 92 } 93 /* scanf("%s", szBuffer); 94 res = TreeQuery(szBuffer); 95 printf("%d\n", res); */ 96 for(list<Node *>::iterator it = nodeMemory.begin();it != nodeMemory.end();it++) 97 { 98 cout<<*it<<endl; 99 } 100 cout<<nodeMemory.size()<<endl; 101 TreeDelete(root); 102 if(nodeMemory.empty()) 103 cout<<"has delete the tire tree"<<endl; 104 cout<<nodeMemory.size()<<endl; 105 system("pause"); 106 return 0; 107 } View Code代碼很簡單,list存儲的是指向內存空間的指針,每次malloc之後會把這個分配的內存指針push到list中,而當free之後,list的就會刪除相應的內容,如果全釋放掉了,則list變為空,從而可以判斷使用後的內存是否全部釋放掉了?
第一次在博客園發博客,之前為了方便在sina寫博客,發現sina不是一般得差,所以搬到這兒來寫了,新的開始,希望大家不吝賜教。
博客參考鏈接:
http://blog.csdn.net/na_he/article/details/7429171
http://baike.baidu.com/view/1068433.htm
http://blog.csdn.net/renkaihao/article/details/6803866