C/C++實戰之記憶體管理 (轉)
歡迎大家來到這片大多數員都心有餘悸的雷區。本世紀偉大的比爾·蓋茨曾經失言:
640K ought to be enough for everybody -- Bill Gates 1981
相信程式設計師們都經常要編寫一些關於分配和使用的程式,而且都有過那種生不如死的感覺(當然我是指那種程式的感覺了,可能誇張了些!)
:namespace prefix = o ns = "urn:schemas--com::office" />
常見的記憶體分配和使用錯誤
1) 記憶體的申請和分配並沒有成功,但程式設計師卻使用了它。一些新手經常會犯這種錯誤,他們並不會留意到記憶體沒有分配成功。判斷指標的值是否為NULL可以有效地避免這種錯誤。
2) 記憶體的分配已經成功,但是卻沒有進行初始化就直接使用它了。首先是觀念上的問題,很多人都沒有在使用指標前要初始化這樣的習慣,然而這個習慣卻是很重要的,希望大家一定要強迫自己養成。第二就是主觀地認為自己申請的記憶體的預設值為0,這樣想是沒有什麼道理的,記憶體分配後的值是不確定的。
3) 上面的兩種工作都已經做好了(已經成功申請並初始化完成),但是操作時卻越界了。
4) 申請了記憶體,使用完了卻忘記了釋放,導致記憶體洩露。這樣的錯誤可以形容為一個惡性的腫瘤,它不會馬上要你的命,但是它會慢慢地吞噬你的資源,直到你的程式徹底完蛋。
5) 你很小心地釋放了記憶體,但是卻又使用了它。由於程式很複雜或者順序出錯,這樣可能導致出現上面的錯誤。
指標---一把偉大的雙刃劍
我真的非常佩服發明指標的人,他簡直太偉大了。能使用如此簡潔地方法將複雜的記憶體結構描述的如此清楚,這本身就是一種偉大的成就。但是,指標之於程式設計師如同武器之於士兵,用好了可以威力無比,用不好則害人害己。
我先說說指標和陣列的區別。陣列名對應著一塊記憶體,它的地址、容量在其生命週期中是不可變的,只有陣列內容是可變的。指標可隨時指向任何型別的記憶體,它的特點就是“變”。指標遠比陣列靈活,但也更危險。
陣列名是不能直接進行賦值和比較的。如果你向要將陣列a賦值給陣列b,不能直接用賦值語句b = a ,這樣會令產生錯誤的。必須使用標準的庫strcpy來進行賦值。相同地,要比較a和b的內容是否相同,不能使用普通的邏輯判斷if(b==a),也要應用庫函式strcmp來判斷。
//陣列……
char a[] = “hello”;
char b[100];
strcpy(b, a); // b = a is wrong
if (strcmp(b, a) == 0) //if (b == a) is wrong
cout<
//指標……
int len = strlen(a);
char *p = (char *)malloc(sizeof(char)*(len+1));
strcpy(p, a);
if (strcmp(p, a) == 0)
cout<
free(p);
在計算記憶體容量的時候有一點是必須要指出的,那就是sizeof計算陣列是計算它的實際的記憶體容量,而計算指標時則永遠都是4個位元組。C++是永遠沒有辦法直到指標所指的記憶體容量,除非在申請時記住它。
free和delete如何對付指標?
程式設計師都知道它們是用來釋放申請的記憶體的,但是卻很少有人注意到指標本身並沒有發生什麼變化。各位可以在VC中使用單步跟蹤一下,你們會驚奇地發現當指標p被呼叫了free後它的地址值並沒有改變,只是該地址對應的記憶體中原來有意義的值變成了垃圾,“p”卻還是指向的這塊記憶體。記住,一定要第一時間將p的值設為NULL,否則會讓別人以為p是一個有意義的指標而誤使用它(當別人使用該指標時會判斷指標的值是否為NULL,如果不為NULL就會以為它有意義)。
char *p = (char *)malloc(100);
strcpy(p, “hello”);
free(p); // the address of “p” is not changed.
….
if (NULL != p) //it will return TRUE
strcpy(p, “world”); //Wrong!!!
下面提兩點,讓大家可以防止上面的情況出現:
1) 指標宣告後要馬上初始化。因為指標出現的預設值是隨機的,所以一定要賦值為NULL,然後再使用。
2) 呼叫了free和delete後一定要將指標賦值為NULL。原因上面已經提過了,就不再贅述了。
本文首先分析了使用記憶體會出現的常見錯誤。然後論述了記憶體使用過程中最為關鍵的一環 — 指標的一些平時不為人注意的用法和技巧。這些都是我平時在做工程專案中積累下的,希望能對大家(特別是那些還在記憶體的苦海中掙扎的苦難弟兄們)會有所幫助。有什麼經驗和問題需要交流的,請我。">paulni@citiz.net
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-990146/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 評C/C++實戰之記憶體管理 (轉)C++記憶體
- 轉載——C++記憶體管理C++記憶體
- C++記憶體管理C++記憶體
- C++記憶體管理剖析C++記憶體
- C++記憶體管理:簡易記憶體池的實現C++記憶體
- 【C/C++】4.C++的記憶體管理C++記憶體
- C++學習體會:記憶體管理C++記憶體
- 記憶體管理兩部曲之實體記憶體管理記憶體
- 記憶體管理之五 (轉)記憶體
- C++動態記憶體管理——new/deleteC++記憶體delete
- C++記憶體管理:new / delete 和 cookieC++記憶體deleteCookie
- C++記憶體模型實踐探索C++記憶體模型
- [C++]記憶體分配C++記憶體
- C++實戰之程式書法 (轉)C++
- C++實戰之資料抽象 (轉)C++抽象
- c++之引用及記憶體分割槽模型C++記憶體模型
- C++ 記憶體對齊C++記憶體
- c++ 記憶體 繼承C++記憶體繼承
- C++記憶體掃描C++記憶體
- C++動態記憶體管理與原始碼剖析C++記憶體原始碼
- c++動態記憶體管理與智慧指標C++記憶體指標
- C和C++的動態記憶體管理的區別C++記憶體
- 記憶體管理篇——實體記憶體的管理記憶體
- C++記憶體池的實現例項C++記憶體
- C# 記憶體管理C#記憶體
- C++手寫記憶體池C++記憶體
- 控制C++的記憶體分配C++記憶體
- C++ 動態記憶體分配C++記憶體
- C++中“記憶體重疊”C++記憶體
- C++動態記憶體分配C++記憶體
- Objective-C 記憶體管理之ARC規則Object記憶體
- C/C++記憶體對齊詳解C++記憶體
- C/C++記憶體分配以及釋放C++記憶體
- C/C++記憶體對齊原則C++記憶體
- 記憶體管理兩部曲之虛擬記憶體管理記憶體
- JAVA記憶體管理 [轉]Java記憶體
- Objective-C 記憶體管理之alloc/retain/release/dealloc實現原理Object記憶體AI
- 【C++】C++ 記憶體分配(new,operator new)詳解C++記憶體