Проблема выделения памяти для глобальной структуры и ее освобождения

#memory-management #malloc #free #dynamic-memory-allocation #freertos

#управление памятью #malloc #Бесплатно #динамическое выделение памяти #freertos

Вопрос:

Я использую встроенную плату с FreeRTOS.

В задаче я определил две структуры и использую pvPortMalloc для выделения памяти. (Одна структура является членом другой)

Кроме того, я передаю адрес struct некоторым функциям.

Однако есть некоторые проблемы с освобождением памяти с помощью vPortFree .

Ниже приведен мой код ( test_task.c ):

 /* Struct definition */
typedef struct __attribute__((packed)) {

        uint8_t  num_parameter;
        uint32_t member1;
        uint8_t  member2;
        uint8_t  *parameter;

}struct_member;

typedef struct __attribute__((packed)) {

        uint16_t num_member; 
        uint32_t class;
        struct_member *member;

}struct_master;
  

Я определяю глобальную структуру и массив ниже.

 uint8_t       *arr;
struct_master master:
  

Определение функции:

 void decode_func(struct_master *master, uint8_t *arr) 
{
   master->member = pvPortMalloc(master->num_member);

   for(int i = 0; i < scr->num_command;   i){
      master->member[i].parameter = pvPortMalloc(master->member[i].num_parameter);
      do_something();
   }  
}
  

Задача операции показана следующим образом.

В конце задачи я хотел бы освободить память:

 void test_task()
{
  decode_func( amp;master, arr);
  do_operation(); 


  vPortFree(master.member);
  for (int i = 0; i < master.num_member;   i)
      vPortFree(master.member[i].parameter);

  hTest_task = NULL;
  vTaskDelete(NULL);    
}
  

Освободить можно . master.member

Однако, когда программа попробовала освободить master.member[i].parameter , кажется, что освобождение было выполнено раньше, и программное обеспечение просто автоматически сбрасывается.

Кто-нибудь знает, почему так произошло?

Ответ №1:

На первый взгляд, способ выделения для членов неверен в decode_func .

Я предполагаю, что master->num_member это указывает на количество struct member s, которое master должно содержать.

 master->member = pvPortMalloc(master->num_member);
  

должно быть исправлено на,

 master->member = pvPortMalloc(master->num_member * sizeof(struct_member));
  

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

    for(int i = 0; i < scr->num_command;   i){
      master->member[i].parameter = pvPortMalloc(master->member[i].num_parameter);
      do_something();
   } 
  

Я не уверен, что src->num_command указывает, но, естественно, я считаю, что цикл должен выполняться до i < master->num_member . Я предполагаю, что ваш цикл также должен быть обновлен следующим образом,

    for(int i = 0; i < master->num_member;   i){
      master->member[i].parameter = pvPortMalloc(master->member[i].num_parameter * sizeof(uint8_t));
      do_something();
   } 
  

При освобождении памяти убедитесь, что вы сначала освободили содержащиеся в ней элементы, прежде чем освобождать структуру контейнера. Поэтому вы должны сначала освободить все parameter s, а затем member , поэтому измените этот порядок в test_task функции.

Также убедитесь, что перед выполнением vTaskDelete(NULL); вы должны освободить все ресурсы, потребляемые test_task , иначе произойдет утечка ресурсов. vTaskDelete(NULL) просто пометит TCB этой конкретной задачи как ready to be deleted , чтобы через некоторое время бездействующая задача очистила ресурсы, связанные с TCB.

Комментарии:

1. Спасибо! Моей ошибкой было указать неправильный размер памяти для master->member

Ответ №2:

Как правило, когда вы освобождаете объект, содержимое объекта уничтожается, и вы больше не можете получить к нему доступ. Поэтому, когда вы хотите освободить вложенные выделения, подобные этому, вам нужно сначала освободить внутренние выделения и только после этого освободить внешнее (основное) выделение. Другими словами:

 for (int i = 0; i < master.num_member;   i)
    vPortFree(master.member[i].parameter);
vPortFree(master.member);
  

сначала освободите параметры, а затем содержащий массив элементов.

Комментарии:

1. Спасибо, что ответили на мой вопрос. Основная проблема заключалась в том, что я выделил память неправильного размера для master->member