2013-03-02 47 views
1

我正在學習C語言,並且在查找如何釋放我的malloc()時遇到問題。簡單程序的內存泄漏,我怎樣才能免費分配?

該程序運行正常..但IM使用Valgrind的,它是未來與8個allocs和5周的FreeS。我需要能夠釋放3個。我評論說我相信我不是免費的,但我不確定是否有解決方案。

有沒有一種方法,我可以釋放這些allocs,或者我需要考慮重新書寫標記生成器()?

下面是代碼整個文件。

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

char *substr(const char *s, int from, int nchars) { 

    char *result = (char *) malloc((nchars * sizeof(char))+1); 
    strncpy(result, s+from, nchars); 

    return result; 
} 

/** 
Extracts white-space separated tokens from s. 
@param s A string containing 0 or more tokens. 
@param ntokens The number of tokens found in s. 
@return A pointer to a list of tokens. The list and tokens must be freed 
by the caller. 
*/ 
char **tokenize(const char *s, int *ntokens) { 
    int fromIndex = 0; 
    int toIndex = 0; 
    char **list; 
    int finalCount = *ntokens; 
    int count = 0; 

    list = malloc(*ntokens * sizeof(char*)); 

    while (count < finalCount) { 

     char *m = strchr(s,' '); 
     toIndex = m - s; 

     if(toIndex >= 0) { 
      list[count] = substr(s,fromIndex,toIndex); // This substr() gets free'ed from main()   
      s = substr(s, toIndex+1, strlen(s)); // I believe This is where I am making extra mallocs that are not being freed 
      count++; 
     } else {   
      list[count] = substr(s,fromIndex,strlen(s)); // This substr() gets free'ed from main() 
      count++; 
     } 
    } 

    return list; 
} 

int main(int argc, char **argv) { 
    char **list; 
    char *string = "terrific radiant humble pig"; 

    int count = 4; // Hard-Coded 

    list = tokenize(string, &count); 

    for (int i=0;i<count;i++) { 
    printf("list[%d] = %s\n", i, list[i]); 
    } 

    // Free mallocs()'s 
    for (int i=0;i<count;i++) { 
    free(list[i]); 
    } 
    // Free List 
    free(list); 

    return 0; 
} 
+0

Wierd,它不給我任何warrnings – John 2013-03-02 02:26:09

+0

你正在編譯-Wall和-Werror? – Asblarf 2013-03-02 02:27:11

+0

關閉主題,但'count ++'不一定在'if/else'中,因爲在這兩種情況下你都會增加計數。 – Asblarf 2013-03-02 02:31:22

回答

2

你在獲得一個令牌後每次都不需要substr。就時間和空間而言,這太浪費了。你可以改變s的值,使它指向你需要的字符串。

//s = substr(s, toIndex+1, strlen(s)); // You don't need have to generate a new string 
s = s + toIndex + 1;//You can just change the value of s to make it point to the string you need 
+0

+1 John你應該接受@JackyZhu的回答;他擊敗了我58秒。 – 2013-03-02 03:44:25

+0

謝謝,那有效! – John 2013-03-02 05:02:38

0

我可以想到一個簡單的解決方法,只需在覆蓋之前將s的當前值存儲在另一個指針中。並且確保不要將s的第一個值直接作爲參數釋放到tokenize()

char **tokenize(const char *s, int *ntokens) { 
    int fromIndex = 0; 
    int toIndex = 0; 
    char **list; 
    int finalCount = *ntokens; 
    int count = 0; 
    bool firstTime = true; // Use this to make sure you do not free up the memory for the initial s passed as the function arg 

    list = malloc(*ntokens * sizeof(char*)); 

    while (count < finalCount) { 
     char *m = strchr(s,' '); 
     toIndex = m - s; 

     if(toIndex >= 0) { 
      const char* previous_s = s; // Store the current value of s 
      list[count] = substr(s,fromIndex,toIndex); // This substr() gets free'ed from main()   
      s = substr(previous_s, toIndex+1, strlen(previous_s)); 
      if (!firstTime) 
      { 
       free(previous_s); // Since we're done with the previous_s, we can free up the memory 
      } 
      firstTime = false; 
      count++; 
     } else {   
      list[count] = substr(s,fromIndex,strlen(s)); // This substr() gets free'ed from main() 
      count++; 
     } 
    } 

    if (!firstTime) 
    { 
     free(s); // There could be a block allocated last time which needs to be freed as well 
    } 

    return list; 
} 
+0

我測試你的記號化,但我很抱歉,郵箱裏收到的信號:「EXC_BAD_ACCESS」。在列表[I] ..while用於執行(INT I = 0; I <計數;我++){ \t \t的printf( 「列表[%d] =%S \ n」 個,I,列表[1]); \t} – 2013-03-02 03:39:00

+1

錯過了返回列表中的令牌化()的結束,已經更新了答案。但正如Jacky Zhu指出的那樣,你不需要在堆中分配和釋放如此多的內存。他的解決方案非常有效。 – Tuxdude 2013-03-02 04:07:28

0

這個問題正是你認爲的原因! 幸運的是在c中很容易移動的點,在哪個字符串處,你不需要再次調用substr;因爲指針;-)

// s = substr(s, toIndex+1, strlen(s)); 
s += toIndex+1; 
+0

非常感謝! – John 2013-03-02 05:12:27