【问题标题】:Problem of allocating memory for a global struct and free it为全局结构分配内存并释放它的问题
【发布时间】:2019-09-10 09:42:39
【问题描述】:

我正在使用带有 FreeRTOS 的嵌入式板。

在一个任务中,我定义了两个结构并使用pvPortMalloc 来分配内存。 (一个结构是另一个结构的成员)

此外,我将结构的地址传递给一些函数。

但是,使用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时, 似乎之前已经执行过释放,软件只是自动重置。

有人知道为什么会这样吗?

【问题讨论】:

    标签: memory-management malloc free dynamic-memory-allocation freertos


    【解决方案1】:

    乍一看,decode_func 中您为成员分配的方式是错误的。

    我假设master-&gt;num_member 表示master 应该包含的struct members 的数量。

    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-&gt;num_command 表示什么,但我自然认为循环应该执行到i &lt; master-&gt;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();
       } 
    

    在释放内存时,请确保在释放容器结构之前先释放包含的成员。因此,您应该首先释放所有的parameters,然后再释放member,所以也要在test_task 函数中更改该顺序。

    还要确保在做vTaskDelete(NULL);之前必须解除分配test_task消耗的所有资源,否则会出现资源泄漏。 vTaskDelete(NULL) 将简单地将特定任务的 TCB 标记为 ready to be deleted,以便稍后空闲任务将清除 TCB 相关资源。

    【讨论】:

    • 谢谢!为master-&gt;member分配错误大小的内存是我的错误
    【解决方案2】:

    通常,当您释放一个对象时,该对象的内容会被销毁,您无法再访问它们。因此,当您想像这样释放嵌套分配时,您需要先释放内部分配,然后才释放外部(主)分配。换句话说:

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

    先释放参数,然后释放包含的成员数组。

    【讨论】:

    • 感谢您回答我的问题。主要问题是我分配了错误大小的内存给master-&gt;member