2014-02-28 71 views
5

我只是學習使用valgrind和c,並且當試圖從結構中釋放數據時,我有一個無效的free()輸出。我相信這是因爲數據沒有正確地從結構中解放出來。作業:釋放結構中的數據

這是我的結構:

typedef struct song_ 
{ 
    char *artist; 
    char *title; 
    mtime *lastPlayed; 
} song; 

這是它試圖釋放它的功能:

void songDelete(song *s) 
{ 
    //artist 
    free(s->artist) ; 
    //title 
    free(s->title) ; 
    //time 
    if(NULL != s->lastPlayed) 
     mtimeDelete(s->lastPlayed) ; 
    //song 
    free(s); 
} 

的mtime和mtimeDelete一些用戶定義的變量和方法,但我覺得他們與我的問題無關。我知道要求某人爲我做作業是錯誤的,如果可能的話,我只想朝正確的方向推動。

+0

你得到的那個無效輸出是什麼? – emecas

回答

3

不,這絕對是正確的做法。

所以,如果valgrind抱怨,這可能是因爲在artisttitlelastPlayed值實際上不是有效的指針。

這是我要檢查的第一件事。

換句話說,確定你在裏面有沒有有效的指針。只需創建一首歌曲:

song *AchyBreakyHeart = malloc (sizeof (song)); 

不會填充字段(它們將被設置爲任意值)。同樣,

AchyBreakyHeart->artist = "Bill Ray Cyrus"; 

將使用字符串常量而不是堆中的有效指針填充它。

理想的事情將有一個「構造」,類似於您所提供的析構函數,是這樣的:

song *songCreate (char *artist, char *title, mtime *lastPlayed) { 
    song *s = malloc (sizeof (song)); 
    if (s == NULL) return NULL; 

    s->artist = strdup (artist); 
    if (s->artist == NULL) { 
     free (s); 
     return NULL; 
    } 

    s->title = strdup (title); 
    if (s->title == NULL) { 
     free (s->artist); 
     free (s); 
     return NULL; 
    } 

    s->lastPlayed = mtimeDup (lastPlayed); 
    if (s->lastPlayed == NULL) { 
     free (s->title); 
     free (s->artist); 
     free (s); 
     return NULL; 
    } 

    return s; 
} 

這保證了對象是完全構造或者根本沒有建造(即沒有半狀態)。

更好的做法是調整構造函數/析構函數對來處理NULL,以便簡化對。首先,稍加修改析構函數,唯一的變化是,它可以接受NULL,而忽略它:

void songDelete (song *s) { 
    // Allow for 'songDelete (NULL)'. 

    if (s != NULL) { 
     free (s->artist); // 'free (NULL)' is valid, does nothing. 
     free (s->title); 
     if (s->lastPlayed != NULL) { 
      mtimeDelete (s->lastPlayed) ; 
     } 
     free (s); 
    } 
} 

接下來,這,而不是試圖記住已分配,而不是將他們全部爲NULL最初構造並且只是調用析構函數,如果出現錯誤:

song *songCreate (char *artist, char *title, mtime *lastPlayed) { 
    // Create song, null all fields to ease destruction, 
    // then only return it if ALL allocations work. 

    song *s = malloc (sizeof (song)); 
    if (s != NULL) { 
     s->artist = s->title = s->lastPlayed = NULL; 

     s->artist = strdup (artist); 
     if (s->artist != NULL) { 
      s->title = strdup (title); 
      if (s->title != NULL) { 
       s->lastPlayed = mtimeDup (lastPlayed); 
       if (s->lastPlayed != NULL) { 
        return s; 
       } 
      } 
     } 
    } 

    // If ANY allocation failed, destruct the song and return NULL. 

    songDelete (s); 
    return NULL; 
} 
+0

謝謝,我一定會檢查一下,確保我做到了這一點。 – bumbleBumble

1

您的代碼顯示正確。

確保您的結構已正確初始化(指針設置爲NULL或有效值)。

int main() { 
    song_ *s = calloc(sizeof(song_)); 
    free(s); 
    return 0; 
} 
+0

'免費(s)'無效。 's'不是一個指針。 – Asblarf

+0

@Asblarf,謝謝。回答編輯。 –

+0

@Asblarf沒有必要調用'free(&s)',因爲'''不是堆在堆中的。 – BlackMamba

0

你創建一個使用malloc(堆分配)的對象/指針你Struct?或者只是song s;(堆棧分配)?

如果它不是malloc'd,或者換句話說你不能釋放一個變量stack,它必須在heap上。

+0

是的,它絕對是用malloc完成的。 (或者它應該和我搞砸了,不過我會檢查以確保我總是使用malloc。) – bumbleBumble