C - 从调用函数中释放内存

时间:2014-08-09 04:13:25

标签: c free

我的主要问题是,我的计划是不是很糟糕的做法?可以吗?它应该完成吗? 我正在编写一个小巧的键值对“字典”结构,只是为了让我自己熟悉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()我分配的字符串数组完成它。但在我继续这样做之前,我只想知道是否以及如何从调用函数中释放内存。我已经阅读了一些关于它的内容,而且所说的只是“程序员有责任在调用函数中释放内存”,但本书没有说明如何处理这种情况。

提前感谢您的帮助!

1 个答案:

答案 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字符串将被释放。