2010-01-31 78 views
1

我有一個函數在程序執行過程中被多次調用。在這個函數中,我有一個動態的字符指針,我可以調整大小。釋放字符指針

我的問題是:我需要在函數結束之前釋放這個指針嗎?

void functionName() 
{ 
char *variable = (char *) malloc(0); 
    //variable is resized with realloc x number of times 

//should free be called here? 
return; 
} 

我也應該注意到,我試圖釋放指針,不過,GDB給我警告,當我這樣做。

+0

什麼警告並GDB給你? – ezod 2010-01-31 20:38:57

回答

3

是的,你必須釋放它,否則你會泄漏內存。你的代碼應該是這個樣子:

void function(void) 
{ 
    char *variable = (char *)malloc(0); 

    variable = realloc(variable, 10); 
    // do something with new memory 

    variable = realloc(variable, 20); 
    // do something with more new memory 

    free(variable); // clean up 
} 

調用malloc(0)是有點不可思議,我想。

+0

gdb給了我: 警告:堆塊在003E2468修改爲003E25C8過去請求的大小爲158 – 2010-01-31 20:40:07

+2

這個警告聽起來像是你在某個時候溢出你的緩衝區,或者用'malloc() '/'realloc()'調用。 – 2010-01-31 20:41:28

+0

事實證明,我並沒有爲我正在輸入的數據重新分配足夠的內存。 感謝您的幫助! – 2010-01-31 20:49:01

0

從手冊頁:

如果大小爲0,那麼malloc()函數返回值爲NULL,或者以後可以順利通過釋放的唯一指針值()。

所以,我相信答案是「是」:)。

0

是的,你需要調用free()一次釋放內存塊。您不需要爲後續的reallocs()函數免費調用,即使這些函數返回不同的地址/指針。內存管理器知道舊塊不再需要,並釋放()它。

0

您應該可以在最後撥打free(variable)。如果realloc有史以來必須移動數據以調整它的大小,它在內部調用free,你不需要擔心。

此外,在初始化variable時,您可以將其設置爲NULL而不是調用malloc; realloc將首次像malloc一樣工作。

0

看一看一些我已經給了一對夫婦的關係問題,內存管理問題的答案:

上述所有的點出了明顯的事情,每一個的malloc有一個免費的,如果不是你有內存泄漏的,所以它是你必須free內存當你與完成你的指針變量是malloc d。

希望這會有所幫助, 最好的問候, 湯姆。

+0

順便說一句,應該指出,有人今天有一個確切的問題,題爲'C stdlib realloc問題'... – t0mm13b 2010-01-31 21:44:58

3

幾個點使:

我看不出你如何在代碼中使用realloc(),但如果你使用它這樣的,這是錯誤的:

variable = realloc(variable, amount); 

當它是無法分配更多內存,realloc()返回NULL,但保持原始指針不變。在上面的行中,這意味着variableNULL,我們已經失去了它指向的內存的訪問權限,但是該內存沒有被釋放。正確的成語是:

void *tmp = realloc(variable, amount); 
if(tmp) 
    { 
    // success! variable invalid, tmp has new allocated data 
    variable = tmp; 
    } 
else 
    { 
    // failure! variable valid, but same size as before, handle error 
    } 

你應該使用第二個是因爲,與realloc(),失敗是壞的,但在許多情況下相當可回收,不像malloc()哪裏失敗通常意味着其原因「停止一切與死亡「。

這是一個比較有爭議的問題,但是您是否應該像以前一樣使用malloc()realloc()作爲返回值。考慮:

// functionally identical in C 
char *a = malloc(10); 
char *b = (char *)malloc(10); 

在C++中,鑄造必須製成,因爲在C++ void *不能隱式轉換爲另一種指針類型。 (我認爲這是一種語言錯誤,但它不是我的判斷依據。)如果您的代碼是C++,那麼無論如何您應該使用newdelete。如果你的代碼是C但需要用C++編譯器進行編譯(出於某種原因),你別無選擇,只能進行強制轉換。如果您不需要使用C++編譯器編譯C代碼(類似於必須在Python解釋器中運行Ruby代碼),請繼續以下幾點,這就是我認爲您不應該投射的原因。

  1. 在C89,如果沒有被聲明使用的功能,它將被隱式地聲明爲返回一個int。如果我們忘記了#include <stdlib.h>並且我們調用malloc(),那麼沒有強制轉換的版本會導致編譯器錯誤(不允許隱式強制轉換intchar *),而帶有強制轉換的版本會(錯誤地)告訴編譯器「我知道這聽起來很瘋狂,但無論如何都要投它。「大多數編譯器會給你一個隱含的(或不兼容的)聲明,像malloc()這樣的內置函數的聲明,但是演員確實很難找到它。

  2. 假設你有一些數據:

    float *array = (float *)malloc(10 * sizeof(float)); 
    

    後來,你發現你需要在你的數據更加精確,並有使這個double陣列。在上面的線,你需要改變不超過3個不同的地方:

    double *array = (double *)malloc(10 * sizeof(double)); 
    

    如果,另一方面,你這樣寫:

    float *array = malloc(10 * sizeof *array); 
    

    你只需要改變floatdouble在1個地方。此外,始終使用sizeof *obj代替sizeof(type)從不使用強制轉換意味着對realloc()以後的調用可以工作沒有任何變化,而使用強制轉換和顯式定義名稱將需要找到任何你叫realloc和改變鑄件和sizeof秒。另外,如果你忘了,而做到這一點:

    double *array = (float *)malloc(10 * sizeof(float)); 
    

    在大多數平臺上,array現在只有5個元素的數組,假設對準不關閉,編譯器不抱怨你將float *分配給double *。有些人認爲編譯器發出的警告是有幫助的,因爲它指出了可能不正確的行。但是,如果我們避免sizeof(type)並避免投射,我們可以看到行不會是不正確,因此讓編譯器引起他們的注意力正在浪費時間來編程。

+0

作爲補充,大多數感覺需要投出malloc結果的人通常不會感覺到需要將參數強制轉換爲free()。通常是沒有真正理解的普通貨物崇拜的確切標誌。 – Secure 2010-01-31 22:26:18

+0

@Secure:更可能是使用C++的標誌,其中有一個從char *到void *的隱式轉換,但不是另一種方式。就我個人而言,我認爲如果在malloc中使用'sizeof(type)',那麼*爲了安全起見,您應該強制鍵入*。在你初始化一個指針變量的情況下,它根本就不安全,但是在賦值的時候是這樣。但是,正如Chris所指出的,你可能不應該在malloc中使用'sizeof(type)'來開始。最好將大小放在將要分配結果的指針上,然後忽略該強制轉換。 – 2010-01-31 22:38:27

+0

@secure:什麼是貨物崇拜? – t0mm13b 2010-01-31 22:39:01

0
int main(int argc, char *argv[]) 
{ 
     char *p = malloc(sizeof(argv[1])); 

     p = argv[1]; 
     printf("%s\n", p); 
     free(p); 
     return 0; 
} 

IAM獲得glibc的錯誤

hello 
*** glibc detected *** ./a.out: munmap_chunk(): invalid pointer: 0x00007fff66be94c6 *** 
======= Backtrace: ========= 
/lib/x86_64-linux-gnu/libc.so.6(+0x7eb96)[0x7f38dca1db96] 
./a.out[0x4005ed] 
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xed)[0x7f38dc9c076d]