2014-07-06 69 views
1

我是一個新的c,爲了解它,我試圖寫一個函數來手動讀取std輸入的字符。該程序將從std讀取行並輸出它們,ant會在遇到空行時結束。雙免費或腐敗錯誤發生時,免費呼叫c

但是,如果輸入流只包含三行或更少的行,它會工作正常,但如果輸入包含4行以上,它總是會停止並顯示錯誤。調用realloc和釋放函數時發生錯誤:'double free或corruption(fasttop):0x0000000001f46030 *',爲什麼?

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

char *readline(int *length) { 
    char ch, *s = NULL, *temp = NULL; 
    int UNIT = 3, size = 0, index = 0; 
    while ((ch = getchar()) != EOF) { 
     if (size == 0 || index >= size) { 
      size += UNIT; 
      temp = realloc(s, sizeof(char) * size); 
      if (s != NULL && temp != s) free(s); 
      s = temp; 
      temp = NULL; 
     } 

     s[index++] = (ch == '\n') ? '\0' : ch; 
     if (ch == '\n') break; 
    } 
    *length = index - 1; 
    return s; 
} 

char **readlines(int *count) { 
    char **lines = NULL, **tempLines = NULL; 
    int UNIT = 1, size = 0, index = 0; 
    int length = 0; 
    char *line = NULL; 
    while ((line = readline(&length)) != NULL) { 
     if (strlen(line) == 0) break; 
     if (size == 0 || index >= size) { 
      size += UNIT; 
      tempLines = realloc(lines, size * sizeof(char *)); 
      if (lines != NULL && tempLines != lines) free(lines); 
      lines = tempLines; 
      tempLines = NULL; 
     } 
     lines[index++] = line; 
    } 
    *count = index; 
    return lines; 
} 

int main(int argc, char *argv[]) { 
    int length = 0, index = 0; 
    char **lines = readlines(&length); 
    printf("The lines you typed are: \n"); 
    for (; index < length; index++) { 
     printf("%5s %s.\n", "-", lines[index]); 
    } 
    return 0; 
} 

的執行結果是:

[email protected]:~/vmshared$ ./mylib2 
abc 
def 
hij 

The lines you typed are: 
    - abc. 
    - def. 
    - hij. 
[email protected]:~/vmshared$ ./mylib2 
11 
22 
33 
44 
*** Error in `./mylib2': double free or corruption (fasttop): 0x00000000017f1030 *** 
+0

你爲什麼用C++標記它? –

+1

你的代碼和問題類似於http://stackoverflow.com/questions/24592631/realloc-invalid-next-size-and-malloc-memory-corruption-fast/24592774 – deviantfan

+0

這個問題已經解決了這個問題:[ C - 如果使用realloc是免費的必需?](http://stackoverflow.com/questions/5426700/c-if-realloc-is-used-is-free-necessary) –

回答

1

因爲你釋放你的數據,然後使用它:

 temp = realloc(s, sizeof(char) * size); 
     if (s != NULL && temp != s) free(s); 

然後意味着你寫釋放的內存 - 這是壞的。

功能realloc可以看作是這樣做的:

void *realloc(void *ptr, size_t new_size) 
{ 
    void* newptr = malloc(size); 
    size_t oldsize = find_size(ptr); 
    memcpy(newptr, ptr, oldsize); 
    free(ptr); 
    return newptr; 
} 

當然,真正realloc是一個複雜得多(因爲它會檢查當前塊,看它是否可以擴展它分配新數據之前),並且可能不會定期致電malloc,但其功能大致如此。

原因存儲比老指針不同變量的realloc的結果是它返回NULL的情況下 - 它不能擴展到新的大小 - 在這一點上,你需要一個temp和原指針,所以你不會泄漏舊指針的內存。

2

有你readlinesreadline功能的問題。您的錯誤是由realloc調用後釋放指針引起的。

tempLines = realloc(lines, size * sizeof(char *)); 
if (lines != NULL && tempLines != lines) free(lines); // wrong 

temp = realloc(s, sizeof(char) * size); 
if (s != NULL && temp != s) free(s); //wrong 

如果內存含量移動到另一個位置,realloc的釋放舊指針爲您服務。
在您的主要功能中,您永遠不會釋放您的lines指針。

0

您應該不是成功調用realloc後釋放原始內存區域。

temp = realloc(s, sizeof(char) * size); 
if (s != NULL && temp != s) free(s); // This is wrong! 

如果realloc移動您的數據,它也將釋放舊區域。你自己不需要這樣做。

0

當您撥打realloc()並且它成功時,舊的內存位置已被釋放,並返回新的位置。新舊地點有可能相同。但是,無論哪種方式,釋放舊指針都是不正確的。立即釋放新的指針會是古怪的。

因此,這個代碼是不正確的:

temp = realloc(s, sizeof(char) * size); 
if (s != NULL && temp != s) 
    free(s); 
s = temp; 
temp = NULL; 

這也許應該是:

temp = realloc(s, size); 
if (temp == NULL) 
    …report error and exit function… 
s = temp; 

沒有必要轉讓後,設置temp = NULL;,但它確實超出邊際沒有特別的傷害(沒法比)減慢了程序的速度。

3

你的問題是在這裏:

temp = realloc(s, sizeof(char) * size); 
if (s != NULL && temp != s) free(s); 

的情況下realloc成功了,你自由srealloc已釋放它。 你可以看到這個answer瞭解更多詳情。