內存洩漏及簡單檢測的一種方法,內存洩漏檢測
1.什麼是內存洩漏(Memory Leak)?
簡單地說就是申請了一塊內存空間,使用完畢後沒有釋放掉。它的一般表現方式是程序運行時間越長,占用內存越多,最終用盡全部內存,整個系統崩潰。由程序申請的一塊內存,且沒有任何一個指針指向它,那麼這塊內存就洩露了。
2.內存洩漏的危害性
從用戶使用程序的角度來看,內存洩漏本身不會產生什麼危害,作為一般的用戶,根本感覺不到內存洩漏的存在。真正有危害的是內存洩漏的堆積,這會最終消耗盡系統所有的內存。主要有以下幾種表現形式:
1)cpu資源耗盡:估計是機器沒有反應了,鍵盤,鼠標,以及網絡等等。這個在windows上經常看見,特別是中了毒。
2)進程id耗盡:沒法創建新的進程了,串口或者telnet都沒法創建了。
3)硬盤耗盡: 機器要死了,交換內存沒法用,日志也沒法用了,死是很正常的。
在我們寫程序的時候,一般會使用malloc,realloc,new等函數從堆中分配到一塊內存,使用完後,程序必須負責相應的調用free或delete釋放該內存塊,否則,這塊內存就不能被再次使用,我們就說這塊內存洩漏了。如果要避免這個問題,還是要從代碼上入手,良好的編碼習慣和規范,是避免錯誤的不二法門。
3.如何檢測內存洩漏?
第一:良好的編碼習慣,盡量在涉及內存的程序段,檢測出內存洩露。當程式穩定之後,在來檢測內存洩露時,無疑增加了排除的困難和復雜度。使用了內存分配的函數,一旦使用完畢,要記得要使用其相應的函數釋放掉。
Heap memory:
malloc\realloc ------ free
new \new[] ---------- delete \delete[]
GlobalAlloc------------GlobalFree
要特別注意數組對象的內存洩漏
MyPointEX *pointArray =new MyPointEX [100];
其刪除形式為:
delete []pointArray ;
第二:將分配的內存的指針以鏈表的形式自行管理,使用完畢之後從鏈表中刪除,程序結束時可檢查改鏈表。
第三:Boost 中的smart pointer。
第四:一些常見的工具插件,如ccmalloc、Dmalloc、Leaky等等。
4.代碼示例
我主要想結合代碼講講第二個方法,設計思想其實很簡單,用到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變為空,從而可以判斷使用後的內存是否全部釋放掉了?
5.最後感想
第一次在博客園發博客,之前為了方便在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