开发者

Freeing memory of structure linked list using expiration of function scope

My goal is to run a API call repeatedly and check for memory leaks.

The API takes in integer input and returns a pointer to the first structure in a linked list of structures as output. Each structure may have struct variables of other types.

In the following code i have tried to represent my problem.

The problem is in callApi() function. I need to dispose of the memory occupied by the structure 'output' that the API() returns. Even if i use free(output) here, it will cause a memory leak because since it points to a linked list of nested structures. (source of info : http://en.wikibooks.org/wiki/C_Programming/Memory_management)

Question: When leaving exiting callApi() call, will the 'output' nested structure expire when control goes out of the function back to main()? Will it free the entire memory occupied?

Please suggest a solution to way to solve this memory leak problem.

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 all开发者_如何学Pythonocation 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;
}


The simple answer is, no, the memory will not "expire" when you exit a function.

The API should provide a way to "free" the returned value, if it is a complex structure. If it doesn't, then traversing the structure yourself and freeing it is probably the only way out.


The first question who is the owner of the structures you are going to free.

It might be that the API returns a pointer to its internal structure, which you must not deallocate (because, for example, it may be shared).

It might be as well that your code is responsible for deallocating the structure itself, but not the other structures that your structure points to. This way you need to just free the returned structure and forget about it.

It might be however that your responsibility is to free the whole object tree starting at the returned structure. In that case it's to be expected that the API has some function which properly deallocates the structure with its descendants for you. If not (which is most likely not the case), you have to free all the resources referenced by your structure, recursively.

You should look up at the APi documentation to find out which if the three cases is your case.


Update:
Explicitly for your case (the whole structure should be deallocated manually), I would use something like that:

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;
}

Note that the function like free_dev_stat ought to be provided by the API itself, if the API developers really intend to let the users deallocate their structures.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜