2013-07-03 155 views
0
gcc (GCC) 4.7.2 
c89 

你好後,釋放內存已遞增指針

All error checking removed from snippet - to keep the code short. 

我釋放,我已經分配並複製一個字符串到一些內存的問題。

我的程序將檢查數字並增加指針,直到它變爲非數字。

當我去釋放內存時,我得到一個無效的自由堆棧轉儲。

我認爲這是因爲我增加了指針,現在它指向字符串的一半,因爲這是非數字開始。 如果我不增加它的自由空間。但是,如果我增加它然後嘗試並釋放,我會得到堆棧轉儲。

int parse_input(const char *input) 
{ 
    char *cpy_input = calloc(strlen(input) + 1, sizeof(char)); 
    size_t i = 0; 

    apr_cpystrn(cpy_input, input, strlen(input) + 1); 



    /* Are we looking for a range of channels */ 
    for(i = 0; i < strlen(cpy_input); i++) { 
     if(isdigit(*cpy_input)) { 
     /* Do something here */ 
      cpy_input++; 
     } 
    } 

    /* Where finished free the memory */ 
    free(cpy_input); /* Crash here */ 

    return 0; 
} 

我通過聲明另一個指針和分配的地址解決了這個問題,所以它指向的第一個字符,然後我釋放該。它工作正常,即

char *mem_input = cpy_input; 
    free(mem_input); 

我的問題是爲什麼我需要聲明另一個指針能夠釋放內存?有沒有另外一種方法呢?

提前許多感謝,

+0

你可以使用另一個變量來處理分配的內存,在那裏宣佈'cpy_input'爲'char * const的cpy_input',重要的是你是你'免費(same_address);'你的malloc'調用了()' –

+0

你只能提供'free()'以前由'malloc()','calloc()'或'realloc()'返回的指針。將指針返回分配的空間是不夠的;它必須完全是返回的值。 –

回答

4

您需要保存原始指針。釋放內存時只能使用原始指針。您可以創建另一個變量來保存原始指針。

或者把循環放在一個單獨的函數中。由於缺省變量是按值傳遞的,即被複制,所以當你改變函數中的指針時,你只能改變指針的副本。

除此之外,你的循環似乎有點奇怪。您循環使用從零到字符串長度的索引,因此您可以輕鬆使用該索引而不是修改指針。要麼,要麼將環路改成類似while (*cpy_input != '\0')的東西。我從來沒有見過這兩個變種混合在一起。

順便說一句,你在該代碼中有一個錯誤。如果當前字符是數字,則只能增加指針。但是,如果第一個字符是一個數字,循環只會循環,直到它到達字符串的結尾,但指針將增加,你會一遍又一遍檢查的第一個字符。如果你只是想從字符串(如果有的話)獲得領先的數字,你可以使用一個循環,如

for (; isdigit(*cpy_input); cpy_input++) 
{ 
    /* do something, using `*cpy_input` */ 
} 

或課程的

for (int i = 0; i < strlen(cpy_input); i++) 
{ 
    /* do something, using `cpy_input[i]` */ 
} 
+0

我認爲把'cpy_input'聲明爲'const'應該是個好習慣。 –

1

你可以改變你的循環爲

for(i = 0; i < strlen(cpy_input); i++) { 
    if(isdigit(cpy_input[i])) { 
    /* Do something here */ 

    } 

}

或者根本指針運算得到的初始值後

1

嘛,當然有是另一種方法:只需將cpy_input指針遞減多少次即可。或者從最終的cpy_input值中減去字符串的長度(假設您保存了它)。這樣你將恢復原始值cpy_input並正確釋放內存。

這裏的底線很簡單:您必須將您從calloc收到的指針值傳遞給free。沒有辦法繞過它。所以,無論如何,你必須能夠獲得原始的指針值。將它保存在另一個指針中實際上是您的情況中的最佳解決方案。但是,如果你知道如何以其他任何方式做到這一點 - 繼續使用你最喜歡的東西。

1

calloc返回指針內存塊被請求內存。因此,您只能釋放從calloc返回的相同指針位置。

無論是自由的原始指針或這個免費的備份副本。

2
char *cpy_input = calloc(strlen(input) + 1, sizeof(char)); 

假設cpu_input0x1000。點是相同的指針應該被釋放在free()

根據您的邏輯,如果輸入長度爲5,則循環後cpy_input指向0x1005位置。如果你調用free(cpy_input)它的free(0x1005),這是免費的無效的指針,它是越來越墜毀。

+1

實際上它會是未定義的行爲 –

1

,瞭解這一點很重要,那指針只是一個內存地址。

背後freecalloc資源管理系統將保留的內存塊相關的一些記賬的數據,尤其是塊有多大,可以通過調用calloc要求。這可能是在某些查詢的容器中,將其存儲與由calloc返回的指針(即cpu_input初始值),或者該信息被存儲在內存中右塊,這是因爲據我所知,比較常見的前。

如果現在通過在cpu_input改變的價值釋放,它要麼不在其查找容器找到這本書保存數據或將查找這本書緊閉數據的指針,它會發現數據的前你的字符串,這可能根本沒有意義。

所以你保持原有的指針的一個拷貝的解決方案是恰當的。