C/C++中傳遞動態內存的一些問題

文章中的例子都來自  《程序員面試寶典》(二)。


看書的時候,發現了幾個動態內存的問題,很經典,自己在編寫程序時也經常要碰到。很多問題,自己也是第一次明白,想了很長時間。


***************題 1 *******************


這是個很經典的問題,回想一下,自己在寫程序時也遇到過這種情況,而且錯誤經常很難發現。

我現在來分析一下錯誤的地方,我們很多人都覺得這樣寫沒問題,這樣也能爲str分配一定長度的空間,這正是我們忽略的地方。可能是我們遇到的傳指針來交換兩個變量的值這樣的例子太多,潛意識中總覺得傳進去一個指針,就萬事大吉了,什麼也能幫我們修改了(不管是賦值,還是申請空間……)。這是個很大的問題,這也正是我們容易出錯的地方,我們忽略了原來我們傳遞指針後,操作的都是指針地址所指向的內容,而這道題操作的確實指針本身。這就是錯誤所在。

這道題毛病出在GetMemory中,函數中的*p實際上是主函數中的str的一個副本,編譯器總是要爲函數的每個參數製作臨時副本。在本例中,p申請了新的內存,只是把p所指的內存地址改變了,但是str絲毫未變。因爲函數GetMemory沒有返回值,因此str並不指向p所申請的那段內存,所以函數並沒有爲str申請一段可用的內存。事實上,每執行一次GetMemory就會申請一塊內存,但申請的內存卻不能有效釋放,結果是內存一直被獨佔,最終造成內存泄漏。

要解決這個問題,可以由於兩種方法,

第一種方法還是用指針,這時我們必須採用指向指針的指針:

第二種方法我們可以用函數返回值來傳遞動態內存:

 

 

***************題 2 *******************

 

很多人看到這個問題時,覺得很簡單。認爲str是一個函數的局部變量,在函數返回時,它的內存被收回,所以指針指的是個未知區域,容易出問題。這樣的返回操作是不允許的。

這樣的回答是對的,因爲我也是這麼回答的。但是先別急,這只是一半,我們其實並沒有把它搞得很明白,再來看書上給的一個例子:

相信很多人(包括我)在這就犯嘀咕了。很多人認爲這兩個題是一樣的,考的內容都是同一個,都是局部變量的問題。要是這樣理解的話,那就錯了。

其實第二個函數是沒問題的,這樣寫就是第一個函數的改進。如果函數寫成指針的形式,就不會報錯。

這兩個例子函數,考察的是我們對局部數組和全局數組的理解。首先我們一定要搞清楚char str[]和char *str的區別:

1、char str[] = “hello word“;是分配一個局部數組。這個局部變量在內存中的棧,共佔了11個字節(後面還有一個/n),這個應該都沒問題能理解。也就是說字符數組所有的內容全部存在函數所使用的內存中的棧。當函數結束時,這部分棧也隨之“丟失“。故str指向了一個空閒區域。

2、而char *str = “hello word“;是分配了一個全局數組。它所對應的是內存中的全局區域。這個局部變量只佔了內存的4個字節(也就是指針str所佔的內存),這個指針是位於內存的棧中,但是它指向全局區域的一串字符串hello word。所以說,在函數結束時,字符串所佔用的內存並不隨之“消失“。消失的只是指針所佔的內存。

所以,第一個函數要是想修改,可以在語句前,加一個static。通過static開闢一段靜態存儲空間,使之也變爲一個全局區域的數據。

 

 




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章