轉自:http://blog.csdn.net/feixiaoxing/article/details/6746335
在我們個人編程的過程當中,記憶體泄露雖然不會像記憶體溢出那樣造成各種莫名奇妙的問題,但是它的危害也是不可忽視的。一方面,記憶體的泄露導致我們的軟體在運行過程中佔用了越來越多的記憶體,佔有資源而又得不到及時清理,這會導致我們程式的效率越來越低;另一方面,它會影響我們使用者的體驗,失去市場的競爭能力。
常見的記憶體泄露是這樣的:
view plain void process(int size) { char* pData = (char*)malloc(size); /* other code */ return; /* forget to free pData */ } 如上圖所示,我們在函數process的處理過程中,每一次都需要對記憶體進行申請,但是在函數結束的時候卻沒有進行釋放。如果這樣的一段代碼出現在業務側,那麼後果是難以想象的。舉個例子來說,如果我們伺服器每秒鐘需要接受100個使用者的並發訪問,每個使用者過來的資料,我們都需要本地申請記憶體重新儲存一份。處理結束之後,如果記憶體沒有得到很好地釋放,就會導致我們伺服器可用的實體記憶體越來越少。一旦達到某一個臨界點之後,作業系統不得不通過內外存的調度來滿足我們申請新記憶體的需求,這在另一方面來講又會降低伺服器服務的品質。
記憶體泄露的危害是不言而喻的,但是尋找記憶體泄露卻是一件苦難而且複雜的工作。我們都知道,解決bug是一件非常簡單的事情,但是尋找bug的出處卻是一件非常吃力的事情。因此,我們有必要在自己編寫代碼的時候,就把尋找記憶體泄露的工作放在很重要的位置上面。那麼有沒有什麼辦法來解決這一問題呢。
我想要做到解決記憶體泄露,必須做到下面兩個方面:
(1)必須記錄記憶體在哪個函數申請的,具體檔案的行數是多少
(2)記憶體應該什麼時候被釋放
要完成第1個條件其實並不困難。我們可以用節點的方法記錄我們申請的記憶體:
a)設定節點的資料結構
view plain typedef struct _MEMORY_NODE { char functionName[64]; int line; void* pAddress; struct _MEMORY_NODE* next; }MEMORY_NODE; 其中 functionName記錄函數名稱,line記錄行數, pAddress記錄分配的地址, next記錄下一個記憶體節點。
b)修改記憶體的分配函數
對業務側的malloc進行函數修改,添加下面一句宏語句
#define malloc(param) MemoryMalloc(__FUNCTION__, __LINE__, param)
在樁函數側書寫下面的代碼
view plain