我只是学习使用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 :(得分:3)
不,这绝对是正确的做法。
因此,如果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;
}
答案 1 :(得分:1)
您的代码显示正确。
确保您的结构已正确初始化(指针设置为NULL
或有效值)。
int main() {
song_ *s = calloc(sizeof(song_));
free(s);
return 0;
}
答案 2 :(得分:0)
您是否使用Struct
(堆分配)创建了malloc
的对象/指针?或只是song s;
(堆栈分配)?
如果没有malloc,你就无法释放它,换句话说,你无法在stack
上释放变量,它必须位于heap
。< / p>