使用函数范围的到期释放结构链表的内存

时间:2010-12-02 12:49:14

标签: c memory-management memory-leaks scope

我的目标是重复运行API调用并检查内存泄漏 API接受整数输入并返回指向结构的链接列表中的第一个结构的指针作为输出。每个结构可能具有其他类型的结构变量。
在下面的代码中,我试图表示我的问题。

问题在于callApi()函数。我需要处理API()返回的结构'output'占用的内存。即使我在这里使用free(输出),它也会导致内存泄漏,因为它指向嵌套结构的链表。 (信息来源:http://en.wikibooks.org/wiki/C_Programming/Memory_management

问题: 当离开退出callApi()调用时,当控件退出函数返回main()时,'output'嵌套结构是否会过期?它会占用整个内存吗?
请提出解决此内存泄漏问题的解决方案。

Can this problem be overcome with C++?

typedef struct{
  int dev_size;
  char *dev_name;
  dev_stat *next_dev;
  mem_stat *mem_info;
} dev_stat

typedef struct{
  int mem_capacity;
  char *mem_name;
} mem_stat

int main()
{
  int input;
  int return_val;
  int callApi(int);
  while(1)
  {
     return_val=callApi(input);
     print return_val;
  }
}

int callApi(int ip)
{
  //Update: Memory allocation is unnecessary as it is done inside the API() call itself
  //dev_stat *output=(dev_stat *)calloc(2,sizeof(dev_stat));
  int ret_val;
  ret_val=API(ip,&output);
  free(output);
  output=NULL;
  return ret_val;
}

2 个答案:

答案 0 :(得分:4)

简单的答案是,不,退出函数时内存不会“过期”。

API 应该提供一种“释放”返回值的方法,如果它是一个复杂的结构。如果没有,那么自己遍历结构并释放它可能是唯一的出路。

答案 1 :(得分:3)

第一个问题是你将要释放的结构的所有者

可能是API返回指向其内部结构的指针,您不能解除分配(因为,例如,它可能是共享的)。

也许你的代码负责释放结构本身,而不是你的结构指向的其他结构。这样你就需要释放返回的结构而忘记它。

但是,您可能需要从返回的结构中释放整个对象树。在这种情况下,可以预期API具有一些功能,可以为您的后代正确地释放结构。如果不是(很可能不是这种情况),则必须以递归方式释放结构引用的所有资源。

您应该查看APi文档,了解这三种情况是哪种情况。


更新:
明确地为你的情况(整个结构应该手动解除分配),我会使用类似的东西:

void free_mem_stat(struct mem_stat* p)
{
    if (!p) return;
    free(p->mem_name);
    free(p);
}

void free_dev_stat(struct dev_stat* p)
{
    // first, clean up the leaves
    for(struct dev_stat* curr = p; curr; curr = curr->next_dev)
    {
        free(curr->dev_name);
        free_mem_stat(curr->mem_info);
    }
    // than, clean up the linked list
    for(struct dev_stat* curr = p; curr; /**/)
    {
        struct dev_stat* next = curr->next_dev;
        free(curr);
        curr = next;
    }
}

int callApi(int ip)
{
    int ret_val;
    struct dev_stat* output;
    ret_val = API(ip, &output);
    free_dev_stat(output);
    return ret_val;
}

请注意,如果API开发人员真的打算让用户释放他们的结构,那么像free_dev_stat这样的函数应该由API本身提供。