如何定位內存泄漏問題


Things You'll Need

  • Proficiency in C++
  • C++ compiler
  • Debugger and other investigative software tools

1

Understand the operator basics. The C++ operator "new" allocates heap memory. The "delete" operator frees heap memory. For every "new," you should use a "delete" so that you free the same memory you allocated:

char* str = new char [30]; // Allocate 30 bytes to house a string. delete [] str; // Clear those 30 bytes and make str point nowhere.

2

Reallocate memory only if you've deleted. In the code below, str acquires a new address with the second allocation. The first address is lost irretrievably, and so are the 30 bytes that it pointed to. Now they're impossible to free, and you have a memory leak:

char* str = new char [30]; // Give str a memory address. // delete [] str; // Remove the first comment marking in this line to correct. str = new char [60]; /* Give str another memory address with the first one gone forever.*/ delete [] str; // This deletes the 60 bytes, not just the first 30.

3

Watch those pointer assignments. Every dynamic variable (allocated memory on the heap) needs to be associated with a pointer. When a dynamic variable becomes disassociated from its pointer(s), it becomes impossible to erase. Again, this results in a memory leak:

char* str1 = new char [30]; char* str2 = new char [40]; strcpy(str1, "Memory leak"); str2 = str1; // Bad! Now the 40 bytes are impossible to free. delete [] str2; // This deletes the 30 bytes. delete [] str1; // Possible access violation. What a disaster!

4

Be careful with local pointers. A pointer you declare in a function is allocated on the stack, but the dynamic variable it points to is allocated on the heap. If you don't delete it, it will persist after the program exits from the function:

void Leak(int x){ char* p = new char [x]; // delete [] p; // Remove the first comment marking to correct. }

5

Pay attention to the square braces after "delete." Use "delete" by itself to free a single object. Use "delete" [] with square brackets to free a heap array. Don't do something like this:

char* one = new char; delete [] one; // Wrong char* many = new char [30]; delete many; // Wrong!

6

If the leak yet allowed - I'm usually seeking it with deleaker (check it here: http://deleaker.com).

Thanks!

 

發生內存錯誤是件非常麻煩的事情。編譯器不能自動發現這些錯誤,通常是在程序運行時才能捕捉到。而這些錯誤大多沒有明顯的症狀,時隱時現,增加了改錯的難度。

 
常見的內存錯誤及其對策如下:
(1)      內存分配未成功,卻使用了它。
編程新手常犯這種錯誤,因為他們沒有意識到內存分配會不成功。常用解決辦法是,在使用內存之前檢查指針是否為 NULL。如果指針p是函數的參數,那么在函數的入口處用assert(p!=NULL)進行檢查。如果是用malloc或new來申請內存,應該用if(p==NULL) 或if(p!=NULL)進行防錯處理。
(2)      內存分配雖然成功,但是尚未初始化就引用它。
犯這種錯誤主要有兩個起因:一是沒有初始化的觀念;二是誤以為內存的缺省初值全為零,導致引用初值錯誤(例如數組)。 內存的缺省初值究竟是什么並沒有統一的標准,盡管有些時候為零值,我們寧可信其無不可信其有。所以無論用何種方式創建數組,都別忘了賦初值,即便是賦零值也不可省略,不要嫌麻煩。
(3)      內存分配成功並且已經初始化,但操作越過了內存的邊界。
例如在使用數組時經常發生下標“多 1”或者“少1”的操作。特別是在for循環語句中,循環次數很容易搞錯,導致數組操作越界。
(4)      忘記了釋放內存,造成內存泄露。
含有這種錯誤的函數每被調用一次就丟失一塊內存。剛開始時系統的內存充足,你看不到錯誤。終有一次程序突然死掉,系統出現提示:內存耗盡。
動態內存的申請與釋放必須配對,程序中 malloc與free的使用次數一定要相同,否則肯定有錯誤(new/delete同理)。
(5)      釋放了內存卻繼續使用它。
 
有三種情況:
A.        程序中的對象調用關系過於復雜,實在難以搞清楚某個對象究竟是否已經釋放了內存,此時應該重新設計數據結構,從根本上解決對象管理的混亂局面
B.        函數的return語句寫錯了,注意不要返回指向“棧內存”的“指針”或者“引用”,因為該內存在函數體結束時被自動銷毀
C.        使用free或delete釋放了內存后,沒有將指針設置為NULL。導致產生“野指針”。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM