2012-01-31 15 views
1

我正在構建一個數組,我希望它是一個固定的大小,因此,當我在文件中讀取它只存儲最後10個命令。該文件似乎正確讀取,它看起來是正確的,當我打印它,但由於某種原因,我的記憶沒有得到釋放。 MAX設置爲1000 並且historySize從用戶讀取更早。我在我的代碼上運行valgrind,當這些函數的調用被註釋掉時,我沒有任何泄漏。泄漏內存和可能的malloc錯誤

我有一個char **歷史在我的#includes

這裏是我的代碼

void setupHistoryFile() 
{ 
    char string[MAX]; 
    FILE *fp; 
    int len; 
    int pos = 0; 
    fp = fopen(".ush_history","r"); 
    if(fp == NULL) 
    { 
     //create the file 
     fp = fopen(".ush_history","w"); 
    } 
    else 
    { 
     history = (char**)malloc(historySize * sizeof(char*));//setup history file 
     fgets(string,MAX,fp); 
     len = strlen(string); 
     if(string[len-1]=='\n') 
      string[len-1]='\0'; 
     while(!feof(fp)) 
     { 
      if(history[pos] != NULL) 
      { 
       free(history[pos]); 
       history[pos]=NULL; 
      } 
      history[pos] = (char*)malloc((strlen(string)+1) * sizeof(char)); 
      //printf("Should be copying %s\n",string);   
      strcpy(history[pos], string);   
      pos++; 
      pos = pos % historySize; 
      fgets(string,MAX,fp); 
      len = strlen(string); 
      if(string[len-1]=='\n') 
       string[len-1]='\0'; 
     } 
    } 
    fclose(fp); 
} 

我確實有這種清潔史上的一個功能,它看起來像這樣

void cleanHistory() 
{ 
    int i; 
    if(history != NULL) 
    { 
     for(i=0;i<historySize;i++) 
     { 
      free(history[i]); 
      history[i] = NULL; 
     } 
     free(history); 
     history = NULL; 
    } 
} 
+0

你確定你的釋放函數'cleanHistory()'在你分配內存的指針數組上調用嗎?你可以在'cleanHistory()'中放置斷點,並檢查這個函數是否被調用。 – 2012-01-31 07:27:54

+0

我在#includes下有一個char **歷史記錄,我可以在調用函數後在main中打印它的內容。 – samack 2012-01-31 07:30:21

+0

valgrind ........ – 2012-01-31 07:32:07

回答

7

當您使用malloc分配內存時,分配的內存塊未初始化。這意味着如果你做了類似history[pos] != NULL的事情,即使你沒有放任何東西,也可能是真的。

爲了確保分配的內存已初始化,請使用callocmemset

編輯 更具體地講,您的這部分代碼將表現不好:

if(history[pos] != NULL) 
{ 
    free(history[pos]); 
    history[pos]=NULL; 
} 

如果你不幸運,history[pos]將包含一些舊數據,這意味着你會嘗試free東西你還沒有分配。

作爲一個小小的附註,你應該循環,而fgets不會返回NULL。因爲它現在你不檢查從fgets錯誤。事情是這樣的:

while (fgets(...) != NULL) 

那麼你不需要雙呼叫fgets,你會停止循環的錯誤和文件結尾。

+1

不要使用'calloc'或'memset'來初始化一個指針數組。使用循環並將每個數組元素設置爲NULL。 NULL的二進制表示可能是大多數系統上的全部位0,但這不是必需的。 – Secure 2012-01-31 08:51:36

+0

@Secure雖然技術上是對的,但是你是否知道NULL與0不同的任何現代和常用計算機(舊的大型機之外)? – 2012-02-01 07:25:11

+0

它通常是編譯器實現的一種選擇,而不是機器。幾年前我有一箇舊的x86編譯器,它使用所有的位1作爲NULL指針。所以理論上,gcc開發人員可以決定在下一個版本中使用它。或者爲每個未來版本使用不同的NULL表示。它會有點瘋狂,但仍然符合。但是,當面對保存一些輕微打字或保持完全便攜的選擇時,我通常更喜歡後者。 – Secure 2012-02-01 21:18:22

0

您爲歷史記錄分配內存,但不會初始化它。這意味着在第一遍歷史記錄中,可能發生history [pos]沒有被分配,也沒有NULL,並且您將嘗試釋放未分配的內存。