#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