为全局结构分配内存并释放它的问题
Problem of allocating memory for a global struct and free it
我正在使用带有 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( &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
,
好像之前已经执行过freeing,软件自动重置了。
有人知道为什么会这样吗?
通常,当您释放一个对象时,该对象的内容将被销毁,您将无法再访问它们。所以当你想像这样释放嵌套分配时,你需要先释放内部分配,然后才释放外部(主)分配。换句话说:
for (int i = 0; i < master.num_member; ++i)
vPortFree(master.member[i].parameter);
vPortFree(master.member);
先释放参数,再释放包含的成员数组。
乍一看,您在 decode_func
中分配成员的方式是错误的。
我假设 master->num_member
表示 master
应该包含的 struct member
的数量。
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
,然后释放 member
,因此还要更改 test_task
函数中的顺序。
还要确保在执行vTaskDelete(NULL);
之前必须释放test_task
消耗的所有资源,否则会出现资源泄漏。 vTaskDelete(NULL)
将简单地将该特定任务的 TCB 标记为 ready to be deleted
,以便在一段时间后空闲任务将清除 TCB 相关资源。
我正在使用带有 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( &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
,
好像之前已经执行过freeing,软件自动重置了。
有人知道为什么会这样吗?
通常,当您释放一个对象时,该对象的内容将被销毁,您将无法再访问它们。所以当你想像这样释放嵌套分配时,你需要先释放内部分配,然后才释放外部(主)分配。换句话说:
for (int i = 0; i < master.num_member; ++i)
vPortFree(master.member[i].parameter);
vPortFree(master.member);
先释放参数,再释放包含的成员数组。
乍一看,您在 decode_func
中分配成员的方式是错误的。
我假设 master->num_member
表示 master
应该包含的 struct member
的数量。
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
,然后释放 member
,因此还要更改 test_task
函数中的顺序。
还要确保在执行vTaskDelete(NULL);
之前必须释放test_task
消耗的所有资源,否则会出现资源泄漏。 vTaskDelete(NULL)
将简单地将该特定任务的 TCB 标记为 ready to be deleted
,以便在一段时间后空闲任务将清除 TCB 相关资源。