[英]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,調用者通過傳遞指針來提供緩沖區以放置結果。 對於長度可變的數據(例如字符串),接口還應允許調用方傳入輸出緩沖區的大小,這一點很重要,這樣該函數可以避免在緩沖區外部進行寫操作。 對於您的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.