C/C++實戰之記憶體管理 (轉)

worldblog發表於2007-12-09
C/C++實戰之記憶體管理 (轉)[@more@] 

歡迎大家來到這片大多數員都心有餘悸的雷區。本世紀偉大的比爾·蓋茨曾經失言:

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/,如需轉載,請註明出處,否則將追究法律責任。

相關文章