2011-02-15 78 views
1

我有一個關於malloc行爲的問題。 有2 C文件如果我們不能釋放它,malloc的行爲是什麼

myTools.c和mainFile.c

mainFile.c是=>

int main(){ 
    int i=1; 
    char *request="blablabla"//vary in situation.Not static 
    while(i==1)//forever Loop 
    { 
     ... 
     strcpy(response,getFile(request)); 
     ... 
    } 
} 

myTools.c是==>

. 
.//something else 
. 
char *getFile(char *request) 
{ 
    char *retVal; 
    ...//some tcp request 
    retVal=malloc(strlen(buffer)); 
    strcpy(retVal,buffer); 
    ..//some char array operations 
    return retVal;  
} 
. 
.//something else 
. 

我不能找到了一種方法來釋放retVal,或者我想知道我需要釋放retVal?

它適用於m68k嵌入式平臺上的uClinux,因此內存有限。

它可能會導致任何內存問題或任何內存不足?

或者影響程序的運行時行爲?

回答

4

每次調用getFile()時都會泄漏內存。

一個解決辦法是:

while(i==1)//forever Loop 
{ 
    ... 
    char* temp = getFile(request); 

    strcpy(response,temp); 

    free(temp); 
    ... 
} 
+0

響應得到它的內存? – 2011-02-15 13:31:29

+2

我們不知道 - 沒有提供那部分源代碼。我認爲它被照顧到別的地方。 – Nick 2011-02-15 13:34:08

+0

但是,如果響應已經指向有效的內存,它應該只是傳遞給getFile()並且什麼都不應該mableced – 2011-02-15 13:37:03

2

既然你回來從getFile()一個指針,也許你可以簡單地把它分配給指針變量在main(),繞過雙用strcpy()?然後你可以在main()內存free()

我不確定,但不明白爲什麼不行。

1

strcpy(response,getFile(request))可能會導致程序崩潰,因爲response指向只讀內存。

1
strcpy(response,getFile(request)); 

應splited到:

char *tmp = getFile(request); 
strcpy(response, tmp); 
free(tmp); 

這有時refered作爲不被推薦的strdup()樣式的分配。 您應該分配的緩衝區像調用代碼:

char *buf2 = malloc(strlen(buffer)); 

,並呼籲

getFile(buf2, strlen(buffer), input); 
// use buf2 
free(buf2); 
1

在嵌入式系統中的malloc()經常被用來在啓動時分配內存將用於在系統運行並從不免費()d。

但是你不應該定期做這樣的事情,因爲如果你不再釋放()它會消耗你的記憶。

你在你的例子中正在做的是在while循環中每一輪泄漏一個值得記憶的內存。

你應該做的是在你的循環中調用free(),但是要注意這仍然可以在長時間運行的嵌入式系統中對內存進行分段。

如果事先你將需要多少內存事先知道:外循環一次的malloc緩衝區並在循環重複使用它:

response = malloc(MAX_BUF_SIZE); 
while (1) { 
    get_file(response, MAX_BUF_SIZE); /* always good to pass the buf size and check */  ... use response ... 
} 

或者,如果你不事先知道大小一個模式可以是:

response = NULL; 
size = 0; 
while (1) { 
    get_file(&response, &size); 
    ... use response ... 
} 

void get_file(char **buf, int *s) 
{ 
    size = ... somehow determine the needed size ... 
    if (size > *s) 
     *buf = realloc(*buf, size);  /* only does free/malloc internaly if it has to no room */ 
    strncpy(*buf, whatver, size); 
} 

你應該總是使用strncpy永不strcpy請!

在您的示例中使用strcpy令人困惑,它無法看到響應獲取其內存,它是靜態分配?它之前是否已經配對?

如果響應已經指向vaid緩衝區,您應該將指針指向緩衝區並傳遞到getFile()並直接將buffer複製到那裏。

如果響應沒有指向有效的內存緩衝區,則無論如何這都不起作用。

0

是的,它最終會導致內存不足,這將導致程序崩潰。

有助於解決此類問題的一條簡單規則是始終記住將 中的內存釋放到與分配位置相同的範圍(如果可能的話)。

在你的情況下,顯然不可能在調用返回之後釋放它,因此在父範圍內實際分配它是有意義的。在main函數中,將分配的指針作爲第二個參數傳遞給getFile函數,並直接寫入它,假設您確保它足夠大以包含所有字符。

0

首先,* retVal的被放置在 的GetFile功能,因而 範圍* retVal的僅限於該特定功能,它使用 將自動設定的內存空間,以釋放功能終止一次 /回報。

變量的範圍決定了它的生命週期/可用性,一旦生命週期結束,並且你不釋放數據塊保留在那裏,它可以通過指針訪問,但是內存塊是一種標記爲免費,之後被覆蓋,沒有任何問題。

其次,尼克是非常正確的,你 會在每次的GetFile時間() 叫浪費內存,因爲它是在主要功能 並具有範圍,直至程序運行。

希望這會有所幫助,如果沒有,我會很樂意幫助只是讓我知道:)

1

每當你創造一些功能,你需要考慮資源管理的界面 - 各種物體的壽命以及這些物體的壽命如何管理。對於沒有實現垃圾收集的C和C++語言尤其如此,但即使在垃圾收集語言中,也需要考慮這一點(對於非內存資源並且可能確保不保存對象引用無限期)。

無論如何,對於C來說,API可以通過多種方式處理'輸出'對象。一些更常見的模式是:

  1. 具有呼叫者提供緩衝或對象位置的結果在
  2. 具有被叫方分配緩衝區或對象,並返回一個指向所分配的對象
  3. 有調用者直接從函數返回對象 - 這僅適用於具有固定大小(內部類型或結構)的項目 - 它不適用於任意字符串。所以我不會進一步討論。

對於選項1,調用者通過傳遞指針提供緩衝區來放置結果。對於可變長度數據,如字符串,重要的是該接口還允許調用者傳遞輸出緩衝區的大小,以避免寫入緩衝區之外。爲了您的getFile()功能,其原型可能看起來像:

int getFile(char const* request, char* result, int result_size); 

的調用者傳遞一個指針放置結果,並在緩衝區中傳遞的大小。該功能可能會在失敗時返回一個負數(比如網絡故障)以及成功時的結果大小。如果成功返回的大小大於提供的緩衝區大小,則調用者知道全部結果未放置在緩衝區中(因爲它不夠大)。如果你走這條路線,考慮'\ 0'終結符字符很重要,並且清楚地指出它是否包含在返回值中,以及如果結果太大(我推薦),是否終止緩衝區。另外,請確保如果傳入一個零大小的緩衝區,函數不會向緩衝區寫入任何內容,而不管是否傳入非NULL指針(這是一種常見模式,可讓函數返回所需的大小在這種情況下的緩衝區)。

對於選項2,該函數將分配一個適當的緩衝區並返回一個指向調用者的指針。在這種情況下,調用者需要有一種方式來釋放緩衝區,以避免內存泄漏。一種方法是記錄調用者需要調用函數返回的指針free()(意味着函數將使用malloc()calloc()分配指針)。另一個是使用函數的接口還包括一個解除分配例程,也許getFile_free()(如果我要走這條路線,我肯定會重新考慮這些函數的命名)。這給了這個API的實現自由分配它返回的緩衝區,但它看起來合適 - 它不限制使用malloc()/free()(儘管它可以)。

對於嵌入式系統(尤其是小型的 - 也許不是基於Linux的系統),我認爲人們可能會選擇選項1.這使得API的用戶可以自由地完全避免動態內存分配,並且它很常見爲嵌入式系統不使用動態內存。此外,使用動態內存分配的系統仍然可以使用選項1的模式 - 它只需要多一點工作,但是該工作可以用與選項2完全相同的東西包裝,因此您可以擁有自己的蛋糕並吃掉它。

相關問題