不,這絕對是正確的做法。
所以,如果valgrind
抱怨,這可能是因爲在artist
,title
或lastPlayed
值實際上不是有效的指針。
這是我要檢查的第一件事。
換句話說,確定你在的裏面有沒有有效的指針。只需創建一首歌曲:
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;
}
你得到的那個無效輸出是什麼? – emecas