簡體   English   中英

如果我們無法釋放它,那么malloc行為是什么?

[英]What is the malloc behaviour if we can't free it

我對malloc行為有疑問。 有2個c文件

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上運行,因此內存有限。

可能會引起任何內存問題或內存不足嗎?

還是影響程序的運行時行為?

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

一種解決方案是:

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

  strcpy(response,temp);

  free( temp );
  ...
}

由於您要從getFile()返回一個指針,也許您可​​以簡單地將其分配給main()的指針變量,而忽略了strcpy()的雙重使用? 然后,您可以free() main()的內存。

我不確定,但不明白為什么這行不通。

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

strcpy(response,getFile(request)); 

應分為:

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

有時將其稱為strdup()樣式分配,不建議這樣做。 您應該在調用代碼中分配緩沖區,例如:

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

並打電話

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

在嵌入式系統中,malloc()通常用於在啟動時分配內存,該內存將在系統運行時使用,從不釋放()d。

但是,您不應該定期執行此類操作,因為如果您不再次使用free(),它將占用您的內存。

在示例中,您正在執行的操作是在while循環中每輪泄漏一個緩沖區的內存。

您應該執行的操作之一是,在循環中調用free(),但要注意,這仍然會使內存碎片化,這在長時間運行的嵌入式系統中尤其糟糕。

如果您事先知道需要多少內存,請在循環外部對內存進行一次分配,然后在循環中重新使用它:

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會造成混淆,無法看到響應從哪里獲取內存,它是靜態分配的嗎? 之前已經分配過嗎?

如果響應已經指向有效緩沖區,則只需將指向緩沖區的指針傳遞給getFile()並直接將buffer復制到那里。

如果響應未指向有效的內存緩沖區,則此方法將無法正常工作。

每當您要為某些功能創建接口時,都需要考慮資源管理-各種對象的生存期如何以及如何管理這些對象的生存期。 對於不實現垃圾回收的語言,例如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()使用malloc() / free() (盡管可以)。

對於嵌入式系統(尤其是小型系統-可能不是基於Linux的系統),我認為人們可能會選擇選項1。這使API的用戶可以完全避免動態分配內存,這對於嵌入式系統來說很常見。不使用動態內存。 同樣,使用動態內存分配的系統仍可以使用選項1的模式-只需花費更多的工作,但是無論如何該工作都可以包裹在與選項2完全一樣的東西中,因此您也可以吃蛋糕。

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

一個有助於解決此類問題的簡單規則是,如果可能的話,請始終記住在與分配內存相同的范圍內釋放內存。

在您的情況下,顯然不可能在調用return之后釋放它,因此在父范圍(即)中實際分配它是有意義的。 main函數中,將分配的指針作為第二個參數傳遞給getFile函數,並直接寫入該函數,前提是您確保它足夠大以包含所有字符。

首先,* retVal放置在getFile函數中,因此* retVal的范圍限於該特定函數,並且一旦函數終止/返回,它使用的內存空間將自動設置為FREE。

變量的范圍決定了它的生命周期/可用性,一旦生命周期結束並且您不釋放數據保留在其中的塊,就可以通過指針對其進行訪問,但是該內存塊被標記為“自由”並被覆蓋之后沒有任何麻煩。

其次,尼克非常正確,每次調用getFile()時都會浪費內存,因為它在主函數中並且具有作用域,直到程序運行為止。

希望這會有所幫助,如果不是這樣,我很樂意提供幫助:)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM