2014-08-29 39 views
11

對於以下代碼: (1)「main」調用函數「f1」。 (2)函數「f1」做了一些數字處理;用malloc創建一個「char」數組,然後將該數組的指針返回給main(不需要取消分配數組)。在函數返回後,函數中分配的內存是否仍然保留分配?

我有3點相關的情況下的問題: (1)我假定,儘管函數「F1」已經終止,所分配的字符數組仍然停留分配直至主程序完全終止。也就是說,分配的內存仍然屬於主內存,其他進程不能從外部訪問(我的意思是干擾)內存。我對嗎? (2)在程序結束之前是否必須釋放數組(在「f1」中分配)(或者一旦主程序終止,它是否被釋放)? (3)如果第二個問題的答案是「是」,那麼如何釋放在另一個函數中分配的數組?

注意:我想保持純c的界限,而不是溢出到C++。

char *f1 (...) { 
    ... 
    ... 
    char *fTmp = malloc (length1 * sizeof (char)); 
    char *fData = malloc (length2 * sizeof (char)); 
    ... 
    ... 
    free (fTmp); 
    return (fData); 
} 

int main() { 
    char *fData = f1 (...); 
    ... 
    return (0); 
} 

回答

14

我認爲,雖然函數「f1」已經終止,但分配的char數組仍然保持分配狀態,直到主程序完全終止。

是的。動態分配的內存與函數無關,它屬於進程。

也就是說,分配的內存仍然屬於主,其他進程不能從外部訪問它。我對嗎?

內存不屬於main()(打算作爲功能),但處理本身(其中main()只是入口點)。在具有內存保護的系統中(每個進程與其他進程隔離),不能從外部訪問。但是,您可以以系統特定的方式進行分配,以跨進程共享內存。

在程序結束之前是否需要釋放數組(在「f1」中分配)(或者一旦主程序終止,它是否被釋放)?

是的。未分配的內存 - 大多數系統中的 - 當進程終止時,操作系統會自動重新分配內存,但這取決於系統。 IMO甚至在操作系統這樣做時,你應該總是釋放,使用這種自動釋放的紅旗(我忘記了釋放,這是一個錯誤?我錯過了什麼?)。此外,如果f1被調用1000次,則每次快速佔用所有可用內存時會泄漏內存。想想服務器中的一個進程,它可能(也應該)啓動並運行多年。

如果第二個問題的答案是「是」,那麼如何釋放在另一個函數中分配的數組?

分配內存的人也可以釋放它,這很好。如果不可能,則調用者將負責這樣的內存。例如,它是什麼strdup()。在這種情況下,被調用的函數必須返回(以某種方式)指向已分配內存的指針(或者可以被另一個特定函數使用的句柄/標記)。例如:

char* pBuffer = f1(); 
// Use it 
free(pBuffer); 

注意,有很多很多的技巧,如果你想隱藏這種內部指針。您可以使用令牌(例如整數,字典中的鍵),typedef或不透明類型。

+1

我正在做同樣的事情;也就是說,我使用通過**的指針在另一個進程中創建的一個進程中釋放了該數組。我不確定我所做的是正確的。所以,你的方法似乎是最接近的答案:「誰分配內存也釋放它是很好的,如果不可能,那麼調用者將負責這樣的內存。」 – ssd 2014-08-29 12:31:42

+1

@ merkez3110但是你不能在進程之間共享指針(除非你在沒有受保護的虛擬內存的環境中運行)。 – 2014-08-29 12:33:10

+1

請原諒我使用錯誤的術語:「過程」。在我上面的評論中,我的意思是在同一個程序中不同的「功能」,而不是不同的過程。 謝謝大家。 – ssd 2014-08-29 12:53:00

1

使用malloc將在堆上分配內存,直到你free它。

這意味着您需要確保每個malloc都有相應的免費,也並非暗示其他進程無法訪問您的數據。這只是一個地址的價值。

在你的主要你必須free(fData)避免內存泄漏。

綜上所述則:

1)你的第一個假設是正確的,第二個和第三個是沒有的。它將保持分配狀態,但它不是本地的,並且 不會被綁定到該進程,因爲它終止了

2)是的,你必須釋放它

3)使用你的函數得到的指針。如果您沒有返回指向您從函數分配的數據的指針,請確保函數free

1
  1. 是的,它仍然在堆中。但是,你對流程的概念感到困惑。除非您創建另一個進程(在* nix上使用fork),否則它仍然是一個進程。

  2. 當不使用內存時釋放內存是個好習慣。但是,如果程序正常結束,分配的內存將被系統釋放。

  3. 像這樣:

    int main() { 
        char *fData = f1 (...); 
        //... 
        free(fData); 
        //... 
    } 
    
4
  1. 是,內存malloc()住宿分配,直到它被釋放。還有什麼其他功能可以將可變大小的數據返回給調用者?

  2. 當程序退出時,所有分配給malloc()的內存都將被釋放。但是,在程序終止之前保留大量不需要的內存通常不是一個好主意,因爲它會影響性能,或者系統可能會耗盡虛擬內存。對於長時間運行的程序來說,這可能是一個特別的問題,它們的內存使用有時會持續增長,直到它們使用所有可用的虛擬內存。

  3. 您可以在函數返回的指針上調用free()。所以在你的情況下,main()完成使用陣列後可以做free(fData)

這應該都包含在任何C編程類或教科書中。

2

malloc在堆上分配內存,因此該內存保持分配狀態直到它被free功能或程序成功終止釋放。
在你的情況下,你在f1中釋放了ftemp,所以它在函數終止後不再存在。 fdata仍在堆中,因爲您正在返回指向該分配位置的指針,因此可以通過main訪問。

一旦main成功終止,fdata指向的內存被釋放。

因此,一旦不再需要它,釋放內存就被認爲是很好的。在程序結束時釋放塊沒有任何意義,因爲當程序終止時(考慮到現代操作系統),程序的所有空間都會返回給系統。

1

在C中可以使用兩種基本類型的內存。兩種類型是堆棧和堆。一般來說,你在一個函數中創建的變量將被分配到堆棧上,並在函數返回時被釋放。在堆中分配的內存將持續存在,並且您有義務在您的程序中管理該分配。堆中的內存將保持分配狀態,直到釋放完爲止使用指向數據塊的指針(內存地址)。

對這兩點有一點閱讀將幫助你理解。我會指出你有兩個fData實例,每個都有自己的範圍。兩個指針指向你分配內存:

char *fData = malloc (length2 * sizeof (char)); 

..即使他們進出的範圍,因爲你的代碼執行。

1

如果你沒有釋放你沒有使用的內存,最終會積累 - 如果你用其他許多指針來做這件事情 - 並且你的程序可能會耗盡內存。在使用free函數釋放內存塊之後,我還建議將NULL指定給指針,因爲即使您已經釋放了指針,如果嘗試訪問指針,也可以獲得未定義的行爲,並在NULL指針操作導致崩潰,所以你很容易能夠跟蹤問題