2013-10-12 63 views
1

我(嘗試?)返回分配給函數內部的內存。在C函數中引用計數和在函數內部分配內存

假設我在這裏寫的東西沒有明顯的問題(並沒有測試)內存是如何釋放或不釋放的?之後我需要free(bob),因爲他不在堆上,對吧?

我在another accepted answer just now的C中讀了一些關於引用計數的內容,但我真的不記得C有什麼像垃圾回收器。

char* strCat5000(char *fmt, ...) 
{ 
    char buff[5000]; 
    char *ret_; 
    va_list arg_ptr; 
    va_start(arg_ptr, fmt); 
    vsnprintf(buff, sizeof(buff), fmt, arg_ptr); 
    va_end(arg_ptr); 
    //ret_ = malloc((char*)(strlen(buff)+1)*sizeof(char)); //Allocated inside function 
    ret_ = (char*)malloc((strlen(buff)+1)*sizeof(char)); //moved (char*) .. typo 
    ret_ = strcpy(ret_,buff); 
    return (ret_); 
} 
... 
void findBob() 
{ 
    char * bob; 
    bob = strCat1000("Server is %s for %d seconds.", "on fire", 35329); 
    printf("%s", bob); 
    free(bob); //bob needs to be freed here or he'll leak when findBob ends??? 
} 
+2

引用計數與垃圾回收沒有關係。這是一種用於管理內存的模式,但它仍然是程序員的手動操作POV –

+0

你是對的,C沒有垃圾收集器。你的代碼有問題嗎? – Barmar

+0

@EdS .:不一定。 Python使用引用計數,它對程序員是透明的。 – icktoofay

回答

1

是的。你必須在findBob()方法中「釋放Bob」,否則在你的程序中沒有關於該特定內存塊的進一步概念=>你將有泄漏。所以,簡而言之:是的,這個記憶必須被釋放。

但是,只是一個方面說明:這種代碼是非常「容易出錯」。如果你有一個功能分配呼叫者應該釋放的內存,那麼有一個方法或類似的方法可能是一個好主意,這使得這個目的非常明顯。調用malloc()free()調用在的相同抽象級別上通常是個好主意。例如。在這種情況下,同一個.c文件中的兩個函數可能是一個合理的「抽象級別」。

+0

我完全不同意這樣的觀點,即釋放第三個函數內部以保留*抽象級別*使得代碼更具可讀性或可維護性,但是...從圍繞interwebs狩獵,這看起來確實是合適的。 – AppFzx

+0

那麼,如果你想到一個公共API(這可能會也可能不是),有一個返回某種形式的數據結構的'get_foo()'方法和一個'free_foo()'方法耦合起來感覺更自然並伴隨它來處理重新分配。是的,它可能像「無意義的額外代碼」,但我認爲它很好。例如,如果'get_foo'會分配一個對象,該對象具有一個必須被釋放的嵌入式額外對象,例如?所以,我其實認爲這種方法很好,它使得代碼在我眼中更加健壯。 –

1

你是對的,如果你從一個函數返回堆分配的數據,它最終需要被釋放(除非你需要它直到程序完成,那麼你可以依賴於所有內存在釋放時該過程退出)。

引用計數是一種用於避免過早釋放內存的技術。如果您可以將一個指針複製到多個變量中,那麼當它們中的任何一個仍在使用它時,您都不想釋放它。您分配一個包含refcount成員的結構。每次將指針指定給另一個變量時,都必須增加refcount,並減少之前變量指向的refcount。當引用計數下降到0時,您可以撥打free()

Wikipedia

+0

「,那麼你可以依賴於當進程退出時所有內存都被釋放的事實。沒錯,但是這種編碼通常被認爲有點草率,我會說...... –

+0

這部分內容:「你可能依賴於當進程退出時所有內存都被釋放的事實」讓​​我感到毛骨悚然。是否在維基百科以外的地方記錄了與所有(有信譽的)編譯器一起工作的跨平臺? – AppFzx

+0

@AppFzx:我不認爲在這不適用的生產環境中會有操作系統。儘管如此,我同意100%,編寫這樣的代碼是不好的做法。當程序退出時運行斷言以確保所有(全局)狀態已被正確釋放,或者類似的東西(當然也執行該釋放操作),這會更好一些。 –

1

要解決上述問題,您有兩種方法。

1st是你在做什麼,那就是free bob在使用後。因爲沒有什麼是automatic在c。

第二是你可以通過parameterstrCat1000其中你想存儲結果(比如說它是store_var)。在這種情況下,store_var將在堆棧中(它必須在findBob內部聲明),並且在findBob結束後它將自動解除分配。

如果你想從free免費獲得免費的malloc

像這樣的東西可以工作:

void findBob() 
{ 
    char store_var[1000]; 
    strCat1000(store_var,"Server is %s for %d seconds.", "on fire", 35329); 
    ... 

void strCat1000(char to_save[],char *fmt, ...) 
{ 
    ret_ = strcpy(to_save,buff); //check for lengths also. 
    ... 
0

要使它真正簡單,我寫的代碼(C++)以下的和平。只需運行它並使用任務管理器監視您的代碼內存使用情況。

#include "stdafx.h" 
#include<iostream> 
#include <conio.h> 

using namespace std; 
int * allocate(unsigned size) 
{ 
    int * arr = new int[size]; 
    for(unsigned i=0;i<size;i++) 
     arr[i] = i; 
    return arr; 
} 
int main() 
{ 
    int * p; 

    p = allocate(1000000); 
    getch(); // Here you still occupy the memory 
    free(p); // here you free the memory you occupy in the function 
    getch(); // here you should see that memory is freed before returning from the main 
    return 0; 
} 
+0

這看起來很合理,但我對這個項目的任意限制只是C,因爲我決定讓C++的許多問題讓我感到不滿。事實上,只要我有時間喘口氣,我就會轉移到http://software.intel.com/en-us/intel-cilk-plus。 – AppFzx