Освобождение памяти связанного списка структур с использованием срока действия функции - PullRequest
0 голосов
/ 02 декабря 2010

Моя цель - многократно запускать вызов API и проверять утечки памяти.
API принимает целочисленный ввод и возвращает указатель на первую структуру в связанном списке структур в качестве вывода.Каждая структура может иметь структурные переменные других типов.
В следующем коде я попытался представить мою проблему.

Проблема в функции callApi ().Мне нужно избавиться от памяти, занятой структурой «output», которую возвращает API ().Даже если я использую здесь free (output), это приведет к утечке памяти, потому что это указывает на связанный список вложенных структур.(источник информации: http://en.wikibooks.org/wiki/C_Programming/Memory_management)

Вопрос: при выходе из вызова callApi () истекает срок действия вложенной структуры output, когда управление выходит из функции обратно в main ()?память занята?
Пожалуйста, предложите решение, как решить проблему утечки памяти.

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 ]

4 голосов
/ 02 декабря 2010

Простой ответ: нет, память не «истекает» при выходе из функции.

API должен предоставить способ «освободить» возвращаемое значение, еслиэто сложная структура.Если этого не произойдет, то, вероятно, единственный выход из структуры и ее освобождение.

3 голосов
/ 02 декабря 2010

Первый вопрос, кто является владельцем структур, которые вы собираетесь освободить.

Возможно, 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;
}

Обратите внимание, что такая функция, как free_dev_stat, должна предоставляться самим API, если разработчики API действительно намерены позволить пользователям освободить свои структуры.

...