我的主要问题是,我的计划是不是很糟糕的做法?可以吗?它应该完成吗? 我正在编写一个小巧的键值对“字典”结构,只是为了让我自己熟悉C.我编写的一个函数旨在返回与提供的键相关的所有值的字符串数组。功能定义:
char** get_values(const struct dict* d, const char* key)
{
// if key does not exist
if(contains_key(d, key) == 0)
{
return NULL;
}
// count the number of times the key occurs in the dict
int count = count_keys(d, key);
// make a return value
char** key_values = alloc_list(count);// definition included below
int curr_count = 0;
// fill return array
for(int pos = 0; pos < DSIZE; pos++)
{// if current key in dict matches requested key...
if(strcmp(d->keys[pos], key) == 0)
{
// add current value to return array
strcpy(key_values[curr_count], d->values[pos]);
curr_count++;
}
}
return key_values;
}
此函数为字符串数组分配内存:
static char** alloc_list(int count)
{
// Allocate list of strings
char** slist = (char**)malloc(sizeof(char*) * count);
// if allocation was great success...
if(slist)
{
// ... allocate memory for each string
for(int pos = 0; pos < DSIZE; pos++)
{
slist[pos] = (char*)malloc(DSIZE * sizeof *slist[pos]);
}
}
return slist;
}
然后在main()中:
add(&dictionary, "a", "a");
add(&dictionary, "a", "aa");
add(&dictionary, "a", "aaa");
char** a_val = get_values(&dictionary, "a"); // TODO: how do I free this!
assert(strcmp(a_val[0], "a") == 0);
assert(strcmp(a_val[1], "aa") == 0);
assert(strcmp(a_val[2], "aaa") == 0); // all these assertions pass
free(*a_val); // with * omitted, execution aborts, with * included, no warnings
// from gcc, yes I am stabbing in the dark here.
a_val = NULL;
我不相信最后两行正在做我希望他们正在做的事情,当我在gdb中打印a_val [0-2]的值时,它们仍然存在。 我意识到我可以通过在main()中分配一个字符串数组来修复这个问题,然后更改get_values()以接受该数组然后让get_values()执行它的业务,然后free()我分配的字符串数组完成它。但在我继续这样做之前,我只想知道是否以及如何从调用函数中释放内存。我已经阅读了一些关于它的内容,而且所说的只是“程序员有责任在调用函数中释放内存”,但本书没有说明如何处理这种情况。
提前感谢您的帮助!
答案 0 :(得分:1)
为了正确释放a_val
,首先需要一个for循环来释放/解除分配先前分配的char数组,然后释放双指针(即a_val
)。否则,您将创建内存泄漏,因为a_val
的元素/指针指向的内存将被取消引用/孤立:
char** a_val = get_values(&dictionary, "a");
...
for(int pos = 0; pos < DSIZE; pos++) {
free(a_val[pos]);
}
free(a_val);
陈述free(*a_val);
等同于陈述free(a_val[0])
。因此,只有第一个a_val
字符串将被释放。